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

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

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

Однако я не осознавал, что все эти механизмы предполагают, что вы контролируете точку, в которой изначально создается тип, а я этого не делаю.

Есть ли у кого-нибудь предложения о том, как я могу лучше подойти к этому?

Большое спасибо


person James Crowley    schedule 11.11.2011    source источник


Ответы (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 (из https://github.com/RickStrahl/Westwind.Utilities/blob/master/Westwind.Utilities/Utilities/ReflectionUtils.cs)

person Rick Strahl    schedule 16.11.2011

Похоже на излишество ... просто создайте новый класс, содержащий только ваши «лишние» свойства. Они определяют статический Dictionary<MainClass,ExtensionsClass>. Когда ваши «осведомленные» компоненты хотят посмотреть на расширенные свойства объекта, они просто ищут этот объект в словаре.

person Robert Levy    schedule 16.11.2011

Вы хотите использовать подход отсюда добавление свойств expando к типизированному объекту во время выполнения в c #

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

person mcintyre321    schedule 06.06.2012