NotifyPropertyChanged - kswoll/someta GitHub Wiki
Hey, you could of course use PropertyChanged.Fody (and you probably should! it offers a number of great features and is well maintained). That said, we think it's also a good example of the power you have at your fingertips with Someta.
So let's define the attribute:
public class NotifyPropertyChangedAttribute : Attribute, IPropertySetInterceptor, IClassEnhancer
{
[InjectAccess("OnPropertyChanged")]
public Action<object, string, object, object> OnPropertyChanged { get; set; }
public void SetPropertyValue(PropertyInfo propertyInfo, object instance, object oldValue,
object newValue, Action<object> setter)
{
if (!Equals(oldValue, newValue))
{
setter(newValue);
OnPropertyChanged(instance, propertyInfo.Name, oldValue, newValue);
}
}
}
Now a sample base class that you would subclass to opt in to INotifyPropertyChanged
behavior:
[NotifyPropertyChanged]
public class BaseClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName, object oldValue, object newValue)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Finally, a sample subclass:
public class TestClass : BaseClass
{
public string StringProperty { get; set; }
}
That's it! To elaborate, the attribute implements both IPropertySetInterceptor
and IClassEnhancer
. It implements IPropertySetInterceptor
which defines the SetPropertyValue
method. It also declares a property of a delegate type that matches the signature of the OnPropertyChanged
method, except it also introduces a new parameter at the front to accomodate the instance. It uses the InjectAccess
attribute to identify the method in your base class that will be called when the property value changes. (Note: if your method has overloads, you should provide an InjectTarget
attribute on your OnPropertyChanged
method to link the method to the injected accessor.)