Динамично добавляющие участники к динамическому объекту

Я ищу способ добавить участников динамично к динамическому объекту. Хорошо, я предполагаю, что немного разъяснения необходимо...

Когда Вы делаете это:

dynamic foo = new ExpandoObject();
foo.Bar = 42;

Bar свойство будет добавлено динамично во времени выполнения. Но код все еще относится "статически" к Панели (имя "Панель" трудно кодируется)... Что, если я хочу добавить свойство во времени выполнения, не зная его имя во время компиляции?

Я знаю, как сделать это с пользовательским динамическим объектом (я на самом деле вел блог об этом несколько месяцев назад), с помощью методов DynamicObject класс, но как я могу сделать это с каким-либо динамическим объектом?

Я мог, вероятно, использовать IDynamicMetaObjectProvider интерфейс, но я не понимаю, как использовать его. Например, какой аргумент должен, я передаю GetMetaObject метод? (это ожидает Expression)

И между прочим, как Вы выполняете отражение о динамических объектах? "Регулярное" отражение и TypeDescriptor не показывайте динамическим участникам...

Любое понимание ценилось бы!

8
задан Thomas Levesque 9 December 2014 в 13:10
поделиться

1 ответ

То, что вы хотите, подобно функциям Getattr / Setattr Python. Там нет встроенного эквивалентного способа сделать это в C # или VB.NET. Внешний слой DLR (который корабли с Ironpython и Ironruby в Microsoft.scripting.dll) включает в себя набор API-хостинга, который включает в себя API Objectoperations, который имеет методы GetMember / SetMember. Вы можете использовать их, но вам понадобится дополнительная зависимость от языка DLR и DLR.

Вероятно, самый простой подход будет создать вызовов с одним из существующих связующих C #. Вы можете получить код для этого, глядя на результат «Foo.bar = 42» в Ildasm или отражатель. Но простой пример этого будет:

object x = new ExpandoObject();
CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
            Binder.SetMember(
                Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
                "Foo",
                null,
                new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
            )
        );
site.Target(site, x, 42);
Console.WriteLine(((dynamic)x).Foo);
9
ответ дан 5 December 2019 в 08:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: