Вопрос

В вопрос О полезности контейнера IOC, выигрышный подавитель отметил, что с контейнером IOC вы можете взять это:

public class UglyCustomer : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            string oldValue = _firstName;
            _firstName = value;
            if(oldValue != value)
                OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            string oldValue = value;
            _lastName = value;
            if(oldValue != value)
                OnPropertyChanged("LastName");
        }
    }
}

к этому:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper()); 

Вопросы:

  • Какой контейнер Magic IOC предоставляет это добро?
  • Пример реализации этого?
  • Любые нисходящие?
  • В проекте со сложными зависимостями я плачу, когда я пытаюсь применить привязку данных с этими объектами?
Это было полезно?

Решение

Для вашего второго кодового фрагмента для работы, NotifyPropertyChangedWrapper наверняка придется использовать отражение (или dynamic) генерировать класс, который предоставляет интерфейс, совместимый с Customer и реализует автоматическое уведомление о свойстве. Не должно быть никаких проблем связывания данных, но было бы немного накладных.

Упрощенная реализация, которая использует динамический объект, может выглядеть что-то подобное:

public class NotifyPropertyChangedWrapper<T> 
    : DynamicObject, INotifyPropertyChanged
{
    private T _obj;

    public NotifyPropertyChangedWrapper(T obj)
    {
        _obj = obj;
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        result = typeof(T).GetProperty(binder.Name).GetValue(_obj);
        return true;
    }

    // If you try to set a value of a property that is
    // not defined in the class, this method is called.
    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        typeof(T).GetProperty(binder.Name).SetValue(_obj, value);
        OnPropertyChanged(binder.Name);
        return true;
    }

    // Implement OnPropertyChanged...
}

Очевидно, любой код, который потребляет один из этих объектов, потеряет бы какой-либо статический тип безопасности. Другой вариант состоит в том, чтобы генерировать класс, реализующий тот же интерфейс, что и класс, завернутый. Есть много примеров для этого в Интернете. Основное требование заключается в том, что ваш Customer должен был бы либо быть interface Или это понадобятся все его свойства, чтобы быть виртуальным.

Другие советы

Для этого в общем случае (то есть единый кусок кода, реализующий inotifyPropertyChanged для любого класса), используйте прокси. Есть много реализации, чтобы сделать это с Castle.dynamicproxy. или Линьфу или Единство. Отказ Эти прокси-библиотеки имеют хорошую поддержку в контейнерах IOC, например, динамичпроток обладают хорошей интеграцией с замком виндзора и перехвата Unity (или все, что называется), явно, явно хорошая интеграция с контейнером Unity.

Я никогда не использовал это, но вы якобы создаете что-то вроде этого, используя Постшарп.

Если вы ищете конкретное решение для автоматически генерирующих обязательных объектов, вы должны смотреть на PropertyChanged.Fody (ранее NotifyPropertyweaver). Это переписывает классы, реализующие inotifyPropertyChanged, чтобы включить код уведомления. На странице GitHub есть пример.

На мой взгляд, это Neater, чем использование предлагаемого раствора контейнера IOC. Тем не менее, это библиотека, специфичная для INOTIFYPROPERTYCHANTED, поэтому не применимо как общее решение, как обсуждалось в вашем связанном вопросе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top