So I'm playing around with WPF/Silverlight and find it quite annoying that you need to provide the string-based name of a property when raising your INotifyPropertyChanged events. So you end up with code like this:
public partial class MyClass : System.ComponentModel.INotifyPropertyChanged {
protected internal void OnPropertyChanged(string propertyName) {
if (PropertyChanged == null) return;
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
private decimal _myProperty;
public virtual decimal MyProperty {
get { return _myProperty; }
set {
if (_myProperty.Equals(value)) return;
_myProperty = value;
OnPropertyChanged("MyProperty"); // <----- This is annoying
}
}
}
The problem here is that you now have a string-based reference to your property name. If you ever change the name of your property, you must remember to change the string. And if you don't remember -- there are no build-time errors to stop you. Thus, there is risk to any refactoring efforts -- something which I like to avoid!
So, how do you fix this. Well, one fairly straightforward way is to use expression trees / lambas to derive the name of your property from an actual reference. In the following code example, I've added a method that takes a lamba and returns the string-based name of the property.
private string GetRefactorproffPropertyName<T>(Expression<Func<T>> property) {
LambdaExpression lambdaExpression = (LambdaExpression)property;
var memberExpression = lambdaExpression.Body as MemberExpression
?? ((UnaryExpression)lambdaExpression.Body).Operand as MemberExpression;
return memberExpression.Member.Name;
}
Now I can modify my property setter like this:
public virtual decimal MyProperty {
get { return _myProperty; }
set {
if (_myProperty.Equals(value)) return;
_myProperty = value;
OnPropertyChanged(GetRefactorproffPropertyName(() => MyProperty)); // <--- this is better (compile-time check)
}
}
Some references: http://stackoverflow.com/questions/3558974/select-a-model-property-using-a-lambda-and-not-a-string-property-name