'System.Collections.Generic.IList<object>' does not contain a definition for 'Add' when using 'dynamic' and 'ExpandoObject'
Asked Answered
A

2

22

Say that I have a class, Foo, looking something like this:

public class Foo : IFoo
{
    public Foo()
    {
        Bars = new List<dynamic>();
    }
    public IList<dynamic> Bars { get; set; }
}

The interface IFoo looks like:

public interface IFoo
{
    IList<dynamic> Bars { get; set; }
}

Now, when I do the following:

IFoo foo = new Foo();
dynamic a = new System.Dynamic.ExpandoObject();
a.Prop = 10000;
dynamic b = new System.Dynamic.ExpandoObject();
b.Prop = "Some Text";
foo.Bars.Add(a); // Throws an 'System.Collections.Generic.IList<object>' does not contain a definition for 'Add' - exception!!!!!
foo.Bars.Add(b); // Same here!!!!!

What am I doing wrong here?????

Algorithm answered 10/4, 2013 at 8:35 Comment(2)
possible duplicate of Can't understand the Exception when using dynamic with generic collection in .net4Flamingo
Would you post the exception that you are getting?Gibbons
H
26

This is a known dynamic binding issue.

Here are some work arounds.

Use ICollection<dynamic> instead:

void Main()
{
    IFoo foo = new Foo();
    dynamic a = new System.Dynamic.ExpandoObject();
    a.Prop = 10000;
    dynamic b = new System.Dynamic.ExpandoObject();
    b.Prop = "Some Text";
    foo.Bars.Add(a);
    foo.Bars.Add(b); 
}

public interface IFoo
{
    ICollection<dynamic> Bars { get; set; }
}

public class Foo : IFoo
{
    public Foo()
    {
        Bars = new List<dynamic>();
    }

    public ICollection<dynamic> Bars { get; set; }
}

Or straight up List<dynamic>:

public interface IFoo
{
    List<dynamic> Bars { get; set; }
}

public class Foo : IFoo
{
    public Foo()
    {
        Bars = new List<dynamic>();
    }

    public List<dynamic> Bars { get; set; }
}

Or use dynamic foo:

void Main()
{
    dynamic foo = new Foo();
    dynamic a = new System.Dynamic.ExpandoObject();
    a.Prop = 10000;
    dynamic b = new System.Dynamic.ExpandoObject();
    b.Prop = "Some Text";
    foo.Bars.Add(a);
    foo.Bars.Add(b); 
}

Or don't dynamic bind add, by casting to object:

void Main()
{
    IFoo foo = new Foo();
    dynamic a = new System.Dynamic.ExpandoObject();
    a.Prop = 10000;
    dynamic b = new System.Dynamic.ExpandoObject();
    b.Prop = "Some Text";
    foo.Bars.Add((object)a); 
    foo.Bars.Add((object)b); 
}

Or be more expressive using a third party framework like my impromptu interface with ActLike & Prototype Builder Syntax (in nuget).

using ImprmoptuInterface;
using Dynamitey;
void Main()
{
    dynamic New = Builder.New<ExpandoObject>();

    IFoo foo = Impromptu.ActLike(
                   New.Foo(
                       Bars: New.List(
                                 New.Obj(Prop:10000),
                                 New.Obj(Prop:"Some Text")
                             )
                       )
                   );
}

public interface IFoo
{
    IList<dynamic> Bars { get; set; }
}
Humectant answered 11/4, 2013 at 13:8 Comment(1)
Thanks a tonne! In my case, using List<dynamic>.Add instead of IList<dynamic>.Add seemed the best option. The containing function returned IList<dynamic> as before.Westering
M
2

I'm not sure if this subverts your particular use case, but:

Try explicitly casting Bars to System.Collections.IList.

((System.Collections.IList)foo.Bars).Add(a);

Source: https://mcmap.net/q/588804/-how-to-add-an-item-of-type-t-to-a-list-lt-t-gt-without-knowing-what-t-is

Alternatively, just redefine Bars as IList rather than IList<dynamic> in your interface + class.

Madore answered 10/4, 2013 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.