Я недавно начал экспериментировать с PostSharp, и я нашел, что особенно полезный аспект автоматизировал реализацию INotifyPropertyChanged. Вы видите пример здесь. Основная функциональность превосходна (все свойства будут уведомлены), но существуют случаи, где я мог бы хотеть подавить уведомление.
Например, я мог бы знать, что особое свойство установлено однажды в конструкторе и никогда не будет изменяться снова. По сути, нет никакой потребности испустить код для NotifyPropertyChanged. Издержки минимальны, когда классы не часто инстанцируют, и я могу предотвратить проблему путем переключения от автоматически сгенерированного свойства до поддержанного полем свойства и записи в поле. Однако, поскольку я изучаю этот новый инструмент, было бы полезно знать, существует ли способ отметить свойство с атрибутом для подавления генерации кода. Я хотел бы смочь сделать что-то вроде этого:
[NotifyPropertyChanged]
public class MyClass
{
public double SomeValue { get; set; }
public double ModifiedValue { get; private set; }
[SuppressNotify]
public double OnlySetOnce { get; private set; }
public MyClass()
{
OnlySetOnce = 1.0;
}
}
Вы можете использовать MethodPointcut вместо MulticastPointcut, то есть использовать Linq-over-Reflection и фильтровать PropertyInfo.IsDefined (ваш атрибут).
private IEnumerable<PropertyInfo> SelectProperties( Type type )
{
const BindingFlags bindingFlags = BindingFlags.Instance |
BindingFlags.DeclaredOnly
| BindingFlags.Public;
return from property
in type.GetProperties( bindingFlags )
where property.CanWrite &&
!property.IsDefined(typeof(SuppressNotify))
select property;
}
[OnLocationSetValueAdvice, MethodPointcut( "SelectProperties" )]
public void OnSetValue( LocationInterceptionArgs args )
{
if ( args.Value != args.GetCurrentValue() )
{
args.ProceedSetValue();
this.OnPropertyChangedMethod.Invoke(null);
}
}
К вашему сведению, у меня были некоторые проблемы с примером на веб-сайте Sharpcrafters, и мне пришлось внести следующие изменения:
/// <summary>
/// Field bound at runtime to a delegate of the method <c>OnPropertyChanged</c>.
/// </summary>
[ImportMember("OnPropertyChanged", IsRequired = true, Order = ImportMemberOrder.AfterIntroductions)]
public Action<string> OnPropertyChangedMethod;
Я думаю, что он вводил элемент OnPropertyChanged, но импортировал до него имел шанс быть создан. Это приведет к сбою OnPropertySet, потому что this.OnPropertyChangedMethod имеет значение null.