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?????

wonea
  • 4,783
  • 17
  • 86
  • 139
Kodo
  • 541
  • 1
  • 6
  • 17
  • 1
    possible duplicate of [Can't understand the Exception when using dynamic with generic collection in .net4](http://stackoverflow.com/questions/7996491/cant-understand-the-exception-when-using-dynamic-with-generic-collection-in-ne) – Paolo Moretti Apr 10 '13 at 10:10
  • Would you post the exception that you are getting? – Ian R. O'Brien Apr 11 '13 at 13:16

2 Answers2

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; }
}
jbtule
  • 31,383
  • 12
  • 95
  • 128
  • Thanks a tonne! In my case, using List.Add instead of IList.Add seemed the best option. The containing function returned IList as before. – Abubakar Mehmood Oct 12 '18 at 09:56
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://stackoverflow.com/a/9468123/364

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

Community
  • 1
  • 1
Matt Mitchell
  • 40,943
  • 35
  • 118
  • 185