Получение значения из динамического объекта динамически - PullRequest
9 голосов
/ 18 декабря 2009

Да, название звучит немного запутанно, поэтому я объясню, что я имею в виду: предположим, у вас есть «динамический» объект C # 4.0 и имя свойства. Как бы вы получили это свойство из динамического объекта?

Другими словами, как бы вы реализовали:

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

Иными словами, я пытаюсь обработать динамический объект как IDictionary.

Обратите внимание, что отражение, скорее всего, здесь не вариант, поскольку динамический объект может быть пользовательской реализацией, не основанной на отражении (например, путем расширения DynamicObject и выполнения своих собственных задач).

Ответы [ 2 ]

14 голосов
/ 18 декабря 2009

Вам нужно будет создать сайт для вызовов, создать связующее и т. Д.

Самый простой способ увидеть, что происходит, это скомпилировать:

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"));
    }
}
3 голосов
/ 14 марта 2011

Платформа с открытым исходным кодом ImpromptuInterface (доступная в nuget) делает это и выполняет дополнительную работу, поскольку кэширование сайта вызовов важно для производительности.

См. InvokeGet

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