是的,标题听起来有点令人困惑,所以我会解释我的意思:假设你有一个C#4.0'动态'对象,以及一个属性的名称。你将如何从动态对象中检索该属性?
换句话说,您将如何实施:
public static object GetDynamicValue(dynamic o, string name) { ... }
另一种说法是我试图将动态对象视为IDictionary。
请注意,这里反射可能不是一个选项,因为动态对象可能是一个不基于反射的自定义实现(例如,通过扩展DynamicObject并做自己的事情)。
答案 0 :(得分:14)
你必须建立一个呼叫站点,创建一个绑定器等。
查看发生了什么的最简单方法是编译:
public static object GetDynamicValue(dynamic o, string name)
{
return o.Foo;
}
然后使用Reflector对其进行反编译并找出它正在做的事情。请注意,它会非常复杂 - 您需要将其从单个静态缓存调用站点更改为在每次调用时创建新站点。
这是一个有效的例子......但它是否完全是否正确是另一回事:)(我完全按照上面的建议去做。)
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Dynamic;
using System.Runtime.CompilerServices;
class Test
{
public static object GetDynamicValue(dynamic o, string name)
{
CallSite<Func<CallSite, object, object>> site
= CallSite<Func<CallSite, object, object>>.Create
(Binder.GetMember(CSharpBinderFlags.None, name,
typeof(Test), new CSharpArgumentInfo[]
{ CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
return site.Target(site, o);
}
static void Main()
{
Console.WriteLine(GetDynamicValue("hello", "Length"));
}
}
答案 1 :(得分:3)
开源框架ImpromptuInterface(在nuget中可用)执行此操作,并执行额外的工作,因为缓存调用站点对性能很重要。
请参阅InvokeGet
public static object GetDynamicValue(dynamic o, string name) {
return Impromptu.InvokeGet(o,name);
}