DynamicObject и ExpandoObject
70C# --- Сборки .NET --- DynamicObject и ExpandoObject
Что, если необходимо создать собственный динамический объект? Для этого на выбор доступно два варианта: наследование от DynamicObject либо использование ExpandoObject. Использование DynamicObject требует немного больше работы, поскольку придется переопределить несколько методов. ExpandoObject представляет собой запечатанный (sealed) класс, готовый к применению.
DynamicObject
Рассмотрим объект, представляющий пользователя. Обычно при этом должны определяться свойства для имени и возраста. Теперь предположим, что необходимо иметь возможность строить такой объект во время выполнения, на основе системы, не имеющей предварительного представления о том, какие свойства могут быть у объекта, и какие методы он может поддерживать. Это именно то, что может обеспечить объект, основанный на DynamicObject. Такая функциональность требуется очень редко, но до настоящего времени язык C# не позволял ее реализовать.
Для начала посмотрим, как выглядит DynamicObject:
using System;
using System.Dynamic;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class MyDynamicObject : DynamicObject
{
Dictionary _dynamic = new Dictionary();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
bool qq = false;
result = null;
if (_dynamic.ContainsKey(binder.Name))
{
result = _dynamic[binder.Name];
qq = true;
}
else
{
result = "Свойство не найдено!";
qq = false;
}
return qq;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dynamic[binder.Name] = value;
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
dynamic method = _dynamic[binder.Name];
result = method((DateTime)args[0]);
return result != null;
}
}
class Program
{
static void Main()
{
}
}
}
В этом примере переопределяются три метода: TrySetMember, TryGetMember и TryInvokeMember.
TrySetMember добавляет новый метод, свойство или поле к объекту. В данном примере информация о членах сохраняется в объекте Dictionary. Объект SetMemberBinder, переданный в TrySetMember, содержит свойство Name, которое используется для идентификации элемента в Dictionary.
TryGetMember извлекает объект, хранящийся в Dictionary, на основе свойства Name из GetMemberBinder.
ExpandoObjeсt
Объект ExpandoObject работает аналогично DynamicObject, который был создан в предыдущем примере. Отличие в том, что никаких методов переопределять не понадобится.
Если нужно управлять добавлением и обращением к свойствам динамического объекта, то наилучшим выбором будет наследование от DynamicObject. Вместе с DynamicObject можно использовать несколько методов для переопределения и точного контроля того, как объект взаимодействует с исполняющей средой. Для прочих случаев подойдет тип dynamic или ExpandoObject.