With arrival of WPF the usage of

INotifyPropertyChanged

interface has expanded dramatically. The most annoying and dangerous part of implementing the interface is, obviously the fact, that you have to pass your option names as strings. This leaves your code prone to bugs - if in 3 months time you rename one of the properties, there is very good chance that you will forget to update the string name as well. In order to overcome the problem we can use some reflection and a little bit of boiler plate code. The good people of the Internet have done all the work for us already, so just copy, paste and enjoy!

Additional advantages of the technique, presented below is better performance, since the parameter objects for property changed events are allocated statically only once. The only drawback is slight increase in the size of static payload size of the class, but not the size of an individual instance. The manual effort you need to put into generating the code cannot be ignored, but is not that large. Aspect oriented programming, such as PostSharp might be a solution to this problem, but it is beyond the scope of this article.

The code below is based on this discussion

First of all add the class below to your project:

public static class TypeManager
    {
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static PropertyInfo GetProperty<TType>(Expression<Func<TType, object>> propertySelector)
        {
            Expression expression = propertySelector.Body;

            // If the Property returns a ValueType then a Convert is required => Remove it
            if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked)
            {
                expression = ((UnaryExpression)expression).Operand;
            }

            // If this isn't a member access expression then the expression isn't valid
            MemberExpression memberExpression = expression as MemberExpression;
            if (memberExpression == null)
            {
                ThrowExpressionArgumentException("propertySelector");
            }

            expression = memberExpression.Expression;

            // If the Property returns a ValueType then a Convert is required => Remove it
            if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked)
            {
                expression = ((UnaryExpression)expression).Operand;
            }

            // Check if the expression is the parameter itself
            if (expression.NodeType != ExpressionType.Parameter)
            {
                ThrowExpressionArgumentException("propertySelector");
            }

            // Finally retrieve the MemberInfo
            PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
            if (propertyInfo == null)
            {
                ThrowExpressionArgumentException("propertySelector");
            }

            return propertyInfo;
        }

        private static void ThrowExpressionArgumentException(string argumentName)
        {
            throw new ArgumentException("It's just the simple expression 'x => x.Property' allowed.", argumentName);
        }

        public static PropertyChangedEventArgs GetPropertyChangedEventArgs<TType>(Expression<Func<TType, object>> propertySelector)

        {
            return new PropertyChangedEventArgs(GetProperty(propertySelector).Name);
        }
    }

Next, when you want to implement the INotifyPropertyChanged interface, you should follow this pattern (read this article for the explanation regarding some attributes in the code):

public class Test : INotifyPropertyChanged 
    {
        [NonSerialized]
        private static readonly PropertyChangedEventArgs _valuePropertyChangedArgs =
            TypeManager.GetPropertyChangedEventArgs<Test>(x => x.Value);

        private string _value:

        public string Value
        {
            get
            {
                return _value;
            }
            set
            {
                if (_value != value)
                {
                    _value = value;
                    OnPropertyChanged(_valuePropertyChangedArgs);
                }
            }
        }

        #region INotifyPropertyChanged Members

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void OnPropertyChanged(PropertyChangedEventArgs propertyChangeArgs)
        {
            PropertyChangedEventHandler h = PropertyChanged;
            if (h != null)
            {
                h(this, propertyChangeArgs);
            }
        }
    }
Tags: computers
Categories: None |

0 comments have been posted.

Your email: we will send you a confirmation link to this address to confirm your identity and to prevent robot posting
Get in touch
»...«
Follow updates

Join our social networks and RSS feed to keep up to date with latest news and publications