Утиная печать / динамические прокси на существующих экземплярах объектов

Я передал объект в нашу библиотеку и прошел через различные процессы. Мне нужно прикрепить некоторую дополнительную информацию к этим объектам, когда они проходят через различные стадии и выходят на другой конец - я думаю, это своего рода динамический шаблон декоратора, за исключением добавления дополнительных свойств, а не изменения существующего поведения.

Я надеялся использовать 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#

Таким образом, вы не получите утечки памяти

Другие вопросы по тегам