Утиная печать / динамические прокси на существующих экземплярах объектов
Я передал объект в нашу библиотеку и прошел через различные процессы. Мне нужно прикрепить некоторую дополнительную информацию к этим объектам, когда они проходят через различные стадии и выходят на другой конец - я думаю, это своего рода динамический шаблон декоратора, за исключением добавления дополнительных свойств, а не изменения существующего поведения.
Я надеялся использовать LinFu или Castle для создания динамического прокси-сервера и реализовать дополнительный интерфейс для объекта, чтобы сохранить это. Компоненты, которые знают о расширенном интерфейсе, могут приводить и получать к нему доступ, тогда как те, которые не являются невидимыми, так как базовый тип не изменился.
Тем не менее, я не оценил, что все эти механизмы предполагают, что у вас есть контроль над точкой, в которой тип создается изначально - а я нет.
У кого-нибудь есть предложения о том, как мне лучше подойти к этому?
Большое спасибо
3 ответа
Это не относится к вашему сценарию точно, но как насчет использования реализации DynamicObject, которая действует как декоратор вокруг вашего объекта? Это позволит вам получить доступ к исходному объекту, а также к дополнительным свойствам. Вроде как ExpandoObject, но начинаю с ваших собственных данных экземпляра.
Что-то вроде этого:
public class Expando : DynamicObject
{
public dynamic Instance;
Dictionary<string, dynamic> ExtraProperties = new Dictionary<string, dynamic>();
public Expando(object instance)
{
Instance = instance;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
try
{
result = ReflectionUtils.GetProperty(Instance, binder.Name);
return true;
}
catch
{
if (ExtraProperties.Keys.Contains(binder.Name))
{
result = ExtraProperties[binder.Name];
return true;
}
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
try
{
ReflectionUtils.SetProperty(Instance, binder.Name, value);
}
catch (Exception ex)
{
ExtraProperties[binder.Name] = value;
}
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
try
{
result = ReflectionUtils.CallMethod(Instance, binder.Name, args);
return true;
}
catch
{}
result = null;
return false;
}
}
К сожалению, он не отвечает вашим строгим требованиям к типизации / интерфейсу, и производительность не будет самой высокой, учитывая использование Reflection здесь (с http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/Westwind.Utilities/Utilities/ReflectionUtils.cs)
Похоже на излишество... просто создайте новый класс, содержащий только ваши "дополнительные" свойства. Определить статический Dictionary<MainClass,ExtensionsClass>
, Когда ваши компоненты "в курсе" хотят посмотреть на расширенные свойства объекта, они просто ищут этот объект в словаре.
Здесь вы хотите использовать подход, добавляющий свойства expando к типизированному объекту во время выполнения в C#
Таким образом, вы не получите утечки памяти