Reflection 向动态对象动态添加成员

Reflection 向动态对象动态添加成员,reflection,dynamic,.net-4.0,c#-4.0,dynamic-language-runtime,Reflection,Dynamic,.net 4.0,C# 4.0,Dynamic Language Runtime,我正在寻找一种将成员动态添加到动态对象的方法。好吧,我想需要澄清一下 当您这样做时: dynamic foo = new ExpandoObject(); foo.Bar = 42; 条属性将在运行时动态添加。但代码仍然“静态地”指向Bar(名称“Bar”是硬编码的)。。。如果我想在运行时添加一个属性,而在编译时不知道它的名称,该怎么办 我知道如何使用DynamicObject类的方法对自定义动态对象(实际上是几个月前)执行此操作,但如何对任何动态对象执行此操作 我可能会使用IDynamicM

我正在寻找一种将成员动态添加到动态对象的方法。好吧,我想需要澄清一下

当您这样做时:

dynamic foo = new ExpandoObject();
foo.Bar = 42;
属性将在运行时动态添加。但代码仍然“静态地”指向Bar(名称“Bar”是硬编码的)。。。如果我想在运行时添加一个属性,而在编译时不知道它的名称,该怎么办

我知道如何使用
DynamicObject
类的方法对自定义动态对象(实际上是几个月前)执行此操作,但如何对任何动态对象执行此操作

我可能会使用
IDynamicMetaObjectProvider
接口,但我不知道如何使用它。例如,我应该向
GetMetaObject
方法传递什么参数?(它需要一个
表达式

顺便问一下,如何在动态对象上执行反射?“常规”反射和
TypeDescriptor
不显示动态成员


如有任何见解,将不胜感激

您想要的类似于Python的getattr/setattr函数。在C#或VB.NET中没有内置的等效方法来实现这一点。DLR的外层(在Microsoft.Scripting.dll中提供了w/IronPython和IronRuby)包括一组托管API,其中包括一个具有GetMember/SetMember方法的ObjectOperations API。您可以使用这些,但需要DLR的额外依赖性和基于DLR的语言

最简单的方法可能是使用现有的C#binder创建一个调用站点。您可以通过查看ildasm或reflector中“foo.Bar=42”的结果来获取此代码。但一个简单的例子是:

object x = new ExpandoObject();
CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
            Binder.SetMember(
                Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
                "Foo",
                null,
                new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
            )
        );
site.Target(site, x, 42);
Console.WriteLine(((dynamic)x).Foo);
object x=newexpandooobject();
CallSite=CallSite.Create(
Binder.SetMember(
Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
“福”,
无效的
新建[]{CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)}
)
);
地点。目标(地点,x,42);
Console.WriteLine(((动态)x.Foo);
开源框架将实现这一点(通过提供)。它在封装的同时仍然缓存@Dino Viehland使用的调用站点和绑定代码

Dynamic.InvokeSet(foo,"Bar",42);

它还可以调用许多函数。

ExpandoObject实现IDictionary,尽管是显式的。这意味着您可以简单地将ExpandooObject强制转换为IDictionary并操作字典

dynamic foo = new ExpandoObject();
foo.Bar = 42;
food = (IDictionary<string,object>)foo;
food["Baz"] = 54
dynamic foo=new ExpandoObject();
foo.Bar=42;
食物=(i词典)foo;
食物[“Baz”]=54

我知道这是一篇很老的文章,但我想我会介绍一下如何在运行时创建自己的类型和添加属性,以防其他人也在寻找类似的东西。

我需要花一些时间来确保我真的理解这段代码在做什么,但不管怎样,它工作得很好。。。谢谢是否可以使用DLR执行此操作?似乎使用dynamic会排除这种情况。上述方法不应正常工作。Setter调用站点要求提供2个参数信息,而不是1个。正确的定义将是:new[]{CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null),CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)}谢谢!事实上,正如我后来意识到的,ExpandooObject实现了IDictionary,因此它显然是这种情况下最简单的解决方案。然而,我的问题范围更广:我正在寻找一种可以处理任何动态对象的解决方案,而不仅仅是ExpandoObjectIn C#6.0,也许你可以像
foo.$Bar=42:)不确定是否允许动态…@nawfal,实际上,该功能已被删除。。。但是无论如何,
foo.$Bar
只是
foo[“Bar”]
Thomas的简写,他不知道该功能被删除了(我很高兴),但是哦,是的,有一刻我忽略了你的q的真正要求。