Getting rid of magic strings in Raise Property Event

Tags: C#

I really dislike magic strings in code, and whenever I can I try to avoid using them either by using constants and what have you. So you can imagine what I felt like when I started raising property change events – all those strings – drive me nuts. Basically copy and paste merchants out there can introduce a whole host of hideous bugs and so I played around with the code so it takes a property delegate into it and uses reflection to raise the correct property name.

So instead of this:

   1: /// <summary>
   2: /// Gets or sets a random property
   3: /// </summary>
   4: public int RandomProperty
   5: {
   6:     get
   7:     {
   8:         return this.randomProperty;
   9:     }
  10:  
  11:     set
  12:     {
  13:         if (!this.randomProperty.Equals(value))
  14:         {
  15:             this.randomProperty = value;
  16:             this.RaisePropertyChanged("RandomProperty");
  17:         }
  18:     }
  19: }

Yuk magic string. You can do this

   1: /// <summary>
   2: /// Gets or sets a random property
   3: /// </summary>
   4: public int RandomProperty
   5: {
   6:     get
   7:     {
   8:         return this.randomProperty;
   9:     }
  10:  
  11:     set
  12:     {
  13:         if (!this.randomProperty.Equals(value))
  14:         {
  15:             this.randomProperty = value;
  16:             this.RaisePropertyChanged(() => this.RandomProperty);
  17:         }
  18:     }
  19: }

By putting the following in a base class.

   1: /// <summary>
   2: /// Raise property event based passed property expression
   3: /// </summary>
   4: /// <typeparam name="T">Type of property</typeparam>
   5: /// <param name="propertyExpresssion">Property expression</param>
   6: protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
   7: {
   8:     var propertyName = this.ExtractPropertyName(propertyExpresssion);
   9:     this.RaisePropertyChanged(propertyName);
  10: }
  11:  
  12: /// <summary>
  13: /// Extracts property name based on reflection
  14: /// </summary>
  15: /// <typeparam name="T">Type of property</typeparam>
  16: /// <param name="propertyExpression">Property expression</param>
  17: /// <returns>Property name</returns>
  18: private string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
  19: {
  20:     if (propertyExpression == null)
  21:     {
  22:         throw new ArgumentNullException("propertyExpression");
  23:     }
  24:  
  25:     var memberExpression = propertyExpression.Body as MemberExpression;
  26:     if (memberExpression == null)
  27:     {
  28:         throw new ArgumentException(@"The expression is not a member access expression.", "propertyExpression");
  29:     }
  30:  
  31:     var property = memberExpression.Member as PropertyInfo;
  32:     if (property == null)
  33:     {
  34:         throw new ArgumentException(@"The member access expression does not access a property.", "propertyExpression");
  35:     }
  36:  
  37:     if (!property.DeclaringType.IsAssignableFrom(this.GetType()))
  38:     {
  39:         throw new ArgumentException(@"The referenced property belongs to a different type.", "propertyExpression");
  40:     }
  41:  
  42:     var getMethod = property.GetGetMethod(true);
  43:     if (getMethod == null)
  44:     {
  45:         // this shouldn't happen - the expression would reject the property before reaching this far
  46:         throw new ArgumentException(@"The referenced property does not have a get method.", "propertyExpression");
  47:     }
  48:  
  49:     if (getMethod.IsStatic)
  50:     {
  51:         throw new ArgumentException(@"The referenced property is a static property.", "propertyExpression");
  52:     }
  53:  
  54:     return memberExpression.Member.Name;
  55: }

Much better…

Add a Comment