How To Get A Property Name Using Lambda Expression in C# 3.0
During development of WPF application using M-V-VM design pattern (by Josh Smith on MSDN Mag.) I came across a problem of refactoring the view model classes, especially the properties’ names. The view model classes are implementing the INotifyPropertyChanged interface by inheriting from a helper NotifyPropertyChanged base class which have a method to raise the property changed event called ‘SendPropertyChanged’. That method gets “propertyName” parameter which is a string, and this was the problem:
My view model properties looks like:
private string m_name;
public string Name
{
get
{
return m_name;
}
set
{
if (m_name != value)
{
m_name = value;
SendPropertyChanged("Name");
}
}
}
the problem here is if I change the property name to “CustomerName” I must ensure to correct the string name in the method parameter. Even worse, if for some reason another method / property is calling ‘SendPropertyChanged’ for the ‘Name’ property it will cause invisible problems (you will see it on the screen, but very difficult to spot). And then:
Lambda Expression to the rescue!
What I wanted to achieve is:
private string m_name;
public string Name
{
get
{
return m_name;
}
set
{
if (m_name != value)
{
m_name = value;
SendPropertyChanged(()=> this.Name);
}
}
}
Note the bolded “() => this.Name”, this will ensure that if anyone changes the name of the property the build will fail (or, using the Refactoring->Rename in VS will change it automatically). After a lot of searches I found the way to do this (in Bernardo Heynemann blog post):
private string GetPropertyName<T>(Expression<Func<T>> property)
{
var propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;
if (propertyInfo == null)
{
throw new ArgumentException("The lambda expression 'property'
should point to a valid Property");
}
var propertyName = propertyInfo.Name;
return propertyName;
}
Note the parameter type Expression<Func<T>> – whenever you cast a delegate (in this case of Func<T>) into Expression you are getting the associated Expression Tree and not the delegate itself. The call is clean and nice due to another feature of C# 3.0 ‘Type inference’ the compiler determines the type of T parameter and does not require us to add the ugly curly brackets.
Enjoy the new revolution!