Запись опубликована
Техно-логи. You can comment here or
there.
При разработке для платформы .NET часто приходится делать так раздражающие всех реализации интерфейса INotifyPropertyChanged на классах-моделях. Типичный пример выглядит так:
class StatisticsRecord: INotifyPropertyChanged
{
private string name;
public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } }
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
}
На мой взгляд, с этим кодом есть 2 проблемы:
- Очень много повторений и кода вызванного необходимостью вызвать NotifyPropertyChanged. Увеличивается количество «тупой» работы.
- Использование строковой константы Name в качестве аргумента. Рефакторинг может привести к разрушению биндинга к такому свойству.
По счастью разработчики симпатичного фреймворка
NInject сделали расширение
Ninject.Extensions.Interception, которое позволяет решить описанные выше проблемы за счет использования динамического AOP. Используется это так:
- Подключаем к проекту библиотеки NInject, Ninject.Extensions.Interception, Castle.Core, Ninject.Extensions.Interception.DynamicProxy
- Создаем класс-реализацию интерфейса IAutoNotifyPropertyChanged, например так:
public class ViewModelBase : IAutoNotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
- Используем этот класс в нашем классе модели. Например:
[NotifyOfChanges]
class StatisticsRecord: INotifyPropertyChanged
{
public virtual string Name { get; set; }
[DoNotNotifyOfChanges]
public virtual string NonNotifyableProperty { get; set; }
}
NB! Важно, чтобы getter-ы и setter-ы были виртуальными, поскольку мы используем DynamicProxy для добавления нотификаций
- Подключаем «перехватчик» при конфигурации ядра NInject:
...
kernel.Components.Add();
...
Код стал короче и понятнее напорядок.
PS. Детали того, как именно это все устроено смотрите тут: