调用动态对象的成员,其名称在运行时在字符串中定义
我想在利用 DLR 绑定机制的同时访问对象的属性。
- 我无法使用本机绑定机制(C# 中的
dynamic
关键字),因为我在编译时不知道属性名称; - 我不能使用反射,因为它只检索静态类型信息;
- 据我所知,转换为
IDictionary
只能解决选择实现该接口的动态类(例如ExpandoObject
)的情况。
这是演示代码:
static void Main(string[] args)
{
dynamic obj = new System.Dynamic.ExpandoObject();
obj.Prop = "Value";
// C# dynamic binding.
Console.Out.WriteLine(obj.Prop);
// IDictionary<string, object>
Console.Out.WriteLine((obj as IDictionary<string, object>)["Prop"]);
// Attempt to use reflection.
PropertyInfo prop = obj.GetType().GetProperty("Prop");
Console.Out.WriteLine(prop.GetValue(obj, new object[] { }));
Console.In.ReadLine();
}
I want to access a property on an object while leveraging the DLR binding mechanism.
- I cannot use the native binding mechanism (
dynamic
keyword in C#) because I do not know the property name at compile-time; - I cannot use reflection because it only retrieves static type information;
- casting to an
IDictionary<string, object>
, to my knowledge, only solves the case of dynamic classes that choose to implement that interface (such asExpandoObject
).
Here is the demonstration code:
static void Main(string[] args)
{
dynamic obj = new System.Dynamic.ExpandoObject();
obj.Prop = "Value";
// C# dynamic binding.
Console.Out.WriteLine(obj.Prop);
// IDictionary<string, object>
Console.Out.WriteLine((obj as IDictionary<string, object>)["Prop"]);
// Attempt to use reflection.
PropertyInfo prop = obj.GetType().GetProperty("Prop");
Console.Out.WriteLine(prop.GetValue(obj, new object[] { }));
Console.In.ReadLine();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我终于能够使用 C# 运行时绑定程序来完成此操作。 (我相信应该可以使用更简单的绑定器实现来做到这一点,但我无法编写一个有效的实现 - 可能编写一个“简单”实现已经相当困难)。
输出:
I was finally able to do it by using the C# runtime binder. (I believe it should be possible to do that with a simpler binder implementation, but I was unable to write a working one - probably writing a "simple" implementation is already quite tough).
Output:
开源框架 dynamitey 将执行此操作(可通过 nuget)。它使用与 C# 编译器相同的 api 调用。
The opensource framework dynamitey will do this (available via nuget). It uses that same api calls as the c# compiler.
您可以将 C#
dynamic
与运行时编译结合使用,以满足未知属性名称的要求。一个例子:
这可行,但我怀疑这是最好的选择,如果您需要调用方法,它可能会变得更复杂一些。
You could use C#
dynamic
with runtime compilation to accommodate the requirement of the unknown property name.An example:
This works, but I doubt that this is the best option and if you need invoke method it can get a bit more complex.
如果您子类化
DynamicObject
,则可以覆盖TrySetMember 按名称将属性存储在本地字典中,并覆盖 TryGetIndex 以使用属性名称作为字符串来检索它们。 DynamicObject 页面上有一个很好的示例在 MSDN 上。这不是最快的方法,因为它没有充分利用动态调度和调用站点(以及其他我不太理解的东西),但它会起作用。它最终会看起来像这样:
If you subclass
DynamicObject
you can override TrySetMember to store the properties by name in a local dictionary, and override TryGetIndex to enable retrieving them using the property name as a string. There's a pretty good example of this at the DynamicObject page on MSDN.This is not the fastest way to do it as it doesn't take advantage of dynamic dispatch and callsites (and other stuff I don't quite understand) as well as it could, but it will work. It'll end up looking like this:
这基本上是这个问题的一个变体:动态添加成员到动态对象,但您不想添加,而是想获取成员 - 因此只需更改活页夹和调用站点的签名即可。看来您已经弄清楚如何制作活页夹了。
This is basically a variant of this question: Dynamically adding members to a dynamic object but instead of wanting to add you're wanting to get the members - so just change the binder and the signature of the call site. It looks like you've already figured out how to make the binder.