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


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.

4

2 回答 2

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; }
}
于 2013-04-11T13:08:46.213 回答
2

我不确定这是否会颠覆您的特定用例,但是:

尝试显式转换BarsSystem.Collections.IList.

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

来源:https ://stackoverflow.com/a/9468123/364

或者,只需重新定义BarsIList而不是IList<dynamic>在您的界面+类中。

于 2013-04-10T08:38:28.863 回答