代码之家  ›  专栏  ›  技术社区  ›  David Ebbo

从动态对象动态获取值

  •  9
  • David Ebbo  · 技术社区  · 15 年前

    是的,标题听起来有点混乱,所以我将解释我的意思:假设您有一个C 4.0“动态”对象,以及一个属性的名称。如何从动态对象中检索该属性?

    换句话说,您将如何实现:

    public static object GetDynamicValue(dynamic o, string name) { ... }
    

    另一种说法是,我试图将动态对象视为IDictionary。

    请注意,反射在这里可能不是一个选项,因为动态对象可能是一个自定义实现,它不是基于反射的(例如,通过扩展dynamic object并执行自己的操作)。

    2 回复  |  直到 15 年前
        1
  •  14
  •   Jon Skeet    15 年前

    你必须建立一个呼叫站点,创建一个活页夹等。

    查看结果的最简单方法是编译:

    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"));
        }
    }
    
        2
  •  3
  •   jbtule    12 年前

    开源框架即兴接口(在nuget中可用)实现了这一点,并完成了所涉及的额外工作,因为缓存调用站点对于性能很重要。

    InvokeGet

    public static object GetDynamicValue(dynamic o, string name) {
            return Impromptu.InvokeGet(o,name);
    }