我正在寻找一种将成员动态添加到动态对象的方法。好的,我想需要进行一些澄清...
当您这样做时:
dynamic foo = new ExpandoObject();
foo.Bar = 42;
Bar
属性将在运行时动态添加。但代码仍然“静态”引用 Bar(名称“Bar”是硬编码的)...如果我想在运行时添加属性而不在编译时知道其名称怎么办?
我知道如何使用自定义动态对象执行此操作(实际上我 几个月前在博客中提到过),使用 DynamicObject
类的方法,但是我如何使用 any 动态对象?
我可能可以使用 IDynamicMetaObjectProvider
接口,但我不明白如何使用它。例如,我应该将什么参数传递给 GetMetaObject
方法? (它需要一个表达式
)
顺便问一下,如何对动态对象执行反射? “常规”反射和 TypeDescriptor
不显示动态成员...
任何见解将不胜感激!
I'm looking for a way to add members dynamically to an dynamic object. OK, I guess a little clarification is needed...
When you do that :
dynamic foo = new ExpandoObject();
foo.Bar = 42;
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 ?
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 ?
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
)
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 !
发布评论
评论(4)
你想要的类似于Python的getattr/setattr函数。在 C# 或 VB.NET 中没有内置等效方法来执行此操作。 DLR 的外层(在 Microsoft.Scripting.dll 中随 IronPython 和 IronRuby 一起提供)包括一组托管 API,其中包括具有 GetMember/SetMember 方法的 ObjectOperations API。您可以使用它们,但需要 DLR 和基于 DLR 的语言的额外依赖性。
最简单的方法可能是使用现有的 C# 绑定器之一创建 CallSite。您可以通过查看 ildasm 或 Reflector 中“foo.Bar = 42”的结果来获取此代码。但一个简单的例子是:
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.
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:
ExpandoObject 实现 IDictionary尽管明确地。这意味着您可以简单地将 ExpandoObject 转换为 IDictionary并操纵字典。
ExpandoObject implements IDictionary<string,object> albeit explicitly. What this means is that you can simply cast the ExpandoObject to IDictionary<string,object> and manipulate the dictionary.
开源框架 Dynamitey 将执行此操作(可通过 nuget)。它进行封装,同时仍然缓存 @Dino-Viehland 使用的调用站点和绑定器代码。
它还可以调用许多其他类型的 C# 绑定器。
The opensource framework Dynamitey will do this (available via nuget). It encapsulates while still caching the call site and binder code that @Dino-Viehland used.
It can also call many other kinds of c# binder too.
我知道这是一篇很旧的帖子,但我想我会传递 Miron Abramson 解决方案,介绍如何创建自己的类型并在运行时添加属性 - 以防其他人退出正在寻找类似的东西。
I know this is quite an old post, but I thought I'd pass along Miron Abramson solution on how you can create your own type and add properties at runtime -- in case anyone else out there is looking for something similar.