【问题标题】:Getting a value from a dynamic object dynamically动态地从动态对象中获取值
【发布时间】:2010-12-27 23:02:45
【问题描述】:

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

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

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

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

请注意,反射在这里可能不是一个选项,因为动态对象可能是不基于反射的自定义实现(例如,通过扩展 DynamicObject 并做自己的事情)。

【问题讨论】:

  • 您能多谈谈您的用例吗?如果您想要一个类似于 IDictionary 的动态对象,为什么不使用 ExpandoObject,例如? Jon 的建议可能有效,但我觉得这对于您正在尝试做的事情来说太复杂了。

标签: c# dynamic c#-4.0


【解决方案1】:

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

查看发生了什么的最简单方法是编译这个:

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"));
    }
}

【讨论】:

  • 非常好,谢谢乔恩!这带来了很多我没有处理过的概念,所以我需要仔细研究它。在那里使用 typeof(Test) 感觉很奇怪,因为它应该无关紧要。但是我尝试将其设置为 null 并且代码仍然有效,所以显然它没有做太多。
  • 它与可访问的成员有关 - 您将能够使用此代码获取 Test 的私有成员,但不能获取其他类型的私有成员。
【解决方案2】:

开源框架 ImpromptuInterface(在 nuget 中可用)执行此操作,并执行所涉及的额外工作,因为缓存调用站点对性能很重要。

InvokeGet

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

【讨论】:

  • @David-Ebbo 虽然 Clay 允许您通过字符串名称访问它自己的属性,但 InvokeGet 允许您通过字符串名称访问任何 IDynamicMetaObjectProvider 属性(或任何比反射更快的常规对象)...除非我错过了什么。
猜你喜欢
  • 2020-10-21
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多