Ответ 1
Я не уверен, есть ли какой-либо метод в структуре, который фактически возвращает GetMemberBinder
, но это не имеет значения - это не правильный способ вызвать динамический член по имени.
Что вам действительно нужно сделать, так это создать сайт вызова. Метод выглядит следующим образом:
static object GetDynamicMember(object obj, string memberName)
{
var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, obj.GetType(),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);
return callsite.Target(callsite, obj);
}
Обратите внимание, что Binder.GetMember
создает CallSiteBinder
, не a GetMemberBinder
. Просто чтобы быть на 100% ясным. Этот метод выдает RuntimeBinderException
, если внутренний вызов TryGetMember
завершается с ошибкой, поэтому вам не нужно проверять результат. Если вы не хотите, чтобы вызывающие абоненты увидели RuntimeBinderException
, затем заверните его в свой собственный try/catch.
Динамическая отправка сложна, по крайней мере, относительно отражения на статических типах. Поскольку CLR на самом деле не динамически типизирован, С# должен фактически создать экземпляр компилятора, чтобы выяснить, как выполнить элемент/метод. Это создание сайта вызова. Насколько мне известно, вы должны это сделать, поэтому каждый метод Binder
возвращает CallSiteBinder
, и вы не можете напрямую создавать какие-либо связующие.
Обратите внимание, что DLR выполняет какое-то кэширование сайта вызова, но я не уверен, что автоматическое кэширование охватывает этот сценарий. Там есть хорошая вероятность, что вы захотите сохранить свой сайт для будущих вызовов, чтобы избежать накладных расходов на постоянную перекомпиляцию.
P.S. Если вы используете (или можете использовать) ExpandoObject
вместо DynamicObject
, то имейте в виду, что он реализует IDictionary<string, object>
, поэтому вам не нужно ничего делать. Просто введите его в тип словаря и проверьте, существует ли свойство. Я бы использовал только DynamicObject
над ExpandoObject
, если бы я делал что-то намного сложнее, чем просто добавлять элементы во время выполнения, т.е. Изменяя фактическое поведение на основе связующего времени выполнения.