I would recommend using string combined with the [CallerMemberName]
attribute.
protected void RaisePropertyChanged([param: Localizable(true)] string validationError, [CallerMemberName]string propertyName = null)
{
// whatever
}
You have to position the propertyName at the end of the parameters, because of the default value, that has to be null
/string.Empty
.
The compiler will replace all calls where propertyName is not provided by the caller with the string of the current property you're in:
public string SomeString
{
get { return _someString}
set
{
_someString = value;
OnPropertyChanged("your validation error");
}
}
will automatically be converted to:
public string SomeString
{
get { return _someString}
set
{
_someString = value;
OnPropertyChanged("your validation error", "SomeString");
}
}
by the compiler!
If you wan't to use it outside of a property, you can call it with nameof(SomeString)
.
I would recommend it over the propertySelector because it is compile time, and doesn't cost you cpu-cycles at runtime. It is also refactoring save other than calling it with a string directly.
When you really need more information about the caller, use propertySelector with expression trees. But there is no need to use cpu-cycles when you can do something at runtime.
For example, the OnPropertyChanged-implementation in Prism by the Microsoft Pattern and Practices team looks like this:
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
// ISSUE: reference to a compiler-generated field
PropertyChangedEventHandler changedEventHandler = this.PropertyChanged;
if (changedEventHandler == null)
return;
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
changedEventHandler((object) this, e);
}
But there is also the propertyExpression version:
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
this.OnPropertyChanged(PropertySupport.ExtractPropertyName<T>(propertyExpression));
}
Which only does more work, because it needs to extract the name over reflection (performance hit) and then calls the original implemenation with the string as parameter.
Thats why nameof()
and/or CallerMemberName
are preferable.