问题描述
我正在寻找一种将成员动态添加到动态对象的方法.好的,我想需要澄清一下...
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(名称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
类的方法,但是我如何使用 任何动态对象?
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
方法?(它需要一个 Expression
)
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...
任何见解将不胜感激!
推荐答案
你想要的是类似于 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.
可能最简单的方法是使用现有的 C# 绑定程序之一创建 CallSite.您可以通过查看 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);
这篇关于向动态对象动态添加成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!