动态地将成员添加到动态对象 [英] Dynamically adding members to a dynamic object
问题描述
我正在寻找一种将动态添加到动态对象的方法。好的,我想有一点澄清是需要的...
I'm looking for a way to add members dynamically to an dynamic object. OK, I guess a little clarification is needed...
当你这样做:
dynamic foo = new ExpandoObject();
foo.Bar = 42;
栏
属性将被动态添加运行。但是代码仍然是静态地到Bar(名称Bar是硬编码的)...如果我想在运行时添加一个属性,而不知道它在编译时的名称怎么办?
The Bar
property will be added dynamically at runtime. But the code still refers "statically" to Bar (the name "Bar" is hard-coded)... What if I want to add a property at runtime without knowing its name at compile time ?
我知道如何使用自定义动态对象(我实际上 DynamicObject 类的方法,一个自定义动态对象/rel =nofollow noreferrer>几个月前)但是如何使用任何动态对象来执行?
I know how to do this with a custom dynamic object (I actually blogged about it a few months ago), using the methods of the DynamicObject
class, but how can I do it with any dynamic object ?
我可以使用 IDynamicMetaObjectProvider
界面,但我不明白如何使用它。例如,我应该向 GetMetaObject
方法传递什么参数? (它期望一个表达式
)
I could probably use the IDynamicMetaObjectProvider
interface, but I don't understand how to use it. For instance, what argument should I pass to the GetMetaObject
method ? (it expects an Expression
)
顺便说一句,你如何对动态对象执行反思? 常规反射和 TypeDescriptor
不显示动态成员...
And by the way, how do you perform reflection on dynamic objects ? "Regular" reflection and TypeDescriptor
don't show the dynamic members...
任何见解将不胜感激!
Any insight would be appreciated !
推荐答案
你想要的是类似于Python的getattr / setattr函数。在C#或VB.NET中没有内置的等效方法。 DLR(与Microsoft.Scripting.dll中的IronPython和IronRuby一起运送)的外层包含一组托管API,其中包含一个具有GetMember / SetMember方法的ObjectOperations API。您可以使用它们,但您需要DLR和基于DLR的语言的额外依赖。
What you want is similar to Python's getattr/setattr functions. There's no built in equivalent way to do this in C# or VB.NET. The outer layer of the DLR (which ships w/ IronPython and IronRuby in Microsoft.Scripting.dll) includes a set of hosting APIs which includes an ObjectOperations API that has GetMember/SetMember methods. You could use those but you'd need the extra dependency of the DLR and a DLR based language.
可能最简单的方法是创建一个CallSite现有的C#绑定器。您可以通过查看ildasm或反射器中的foo.Bar = 42的结果来获取代码。但是一个简单的例子是:
Probably the simplest approach would be to create a CallSite w/ one of the existing C# binders. You can get the code for this by looking at the result of "foo.Bar = 42" in ildasm or reflector. But a simple example of this would be:
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);
这篇关于动态地将成员添加到动态对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!