Switch-case on Class.PropertyName (not value)

I have a class that implements INotifyPropertyChanged as follows:

 public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; string _color; public string Color { get{ return _color; } set { _color = value; RaisePropertyChanged(); } } ... private void RaisePropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } 

When the set Color tool is called, it calls RaisePropertyChanged() , which automatically gets the property name ie "Color" and uses this to populate PropertyChangedEventArgs . Instead of manually entering the property name.

This is good because it prevents possible errors in your code, since you do not need to manually enter the property name. It also helps in refactoring your code, since you are not hard-coded for any lines.

My question
I have an event handler for PropertyChanged . How can I use the switch-case construct without hard coding Property names as strings. So something like this:

 void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){ switch (e.PropertyName) { case PropertyNameOf(Person.Color); //some stuff break; default: break; } } 

Is it possible? I want to do this in order to maintain the benefits that I mentioned above.

+6
source share
2 answers

You can use Expression<Func<T>> to do what you want.

Define this method:

 private string ToPropertyName<T>(Expression<Func<T>> @this) { var @return = string.Empty; if (@this != null) { var memberExpression = @this.Body as MemberExpression; if (memberExpression != null) { @return = memberExpression.Member.Name; } } return @return; } 

Then you can write this:

 void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){ switch (e.PropertyName) { case ToPropertyName(() => Person.Color); //some stuff break; default: break; } } 

Now you have a lot of joy. :-)


To get switching functionality without switch and messy if / then / else , you can do this:

 void Person_PropertyChanged(object sender, PropertyChangedEventArgs e) { var @switch = new Dictionary<string, Action>() { { ToPropertyName(() => Person.Color), () => { /* some stuff */ } }, { ToPropertyName(() => Person.Size), () => { /* some other stuff */ } }, { ToPropertyName(() => Person.Shape), () => { /* some more stuff */ } }, }; if (@switch.ContainsKey(e.PropertyName)) { @switch[e.PropertyName](); } else { /* default stuff */ } } 
+7
source

In C # 6.0, you can use the nameof () keyword.

The keyword is replaced with string literals at compile time. So this is much better than using a lambda expression with code that digs the name of your character at runtime in terms of performance, and also works with switch() :

 switch(e.PropertyName) { case nameof(Foo.Bar): break; } 

You will also get a compile-time error if you change the name of the property in the class, but forget to change it in the switch statement. Thus, this approach is much less error prone.

+5
source

Source: https://habr.com/ru/post/982581/


All Articles