Geeks With Blogs
Brian Schroer Don't Call Me Mort!

 

In my last post, I talked about using a Visual Studio code snippet for properties in classes implementing INotifyPropertyChanged:

The code snippet lets me create the properties faster, but it's still a lot of repetitive "setter" code for each.

What if I moved the "has the value changed?" and backing field update logic out of the property setters and replace my NotifyPropertyChanged method with this CheckForPropertyChange method?:

        protected bool CheckForPropertyChange<T>
            (ref T currentValue, T value, params string[] propertyName)
        {
            if (value.Equals(currentValue)) return false;
 
            currentValue = value;
 
            if (PropertyChanged == null) return false;
 
            foreach (string name in propertyName)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
 
            return true;
        }

 

…so my property code can look like this:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange<string>(ref _statusMessage, value, "StatusMessage"); }
        }

 

Actually, the generic type (<string> in the example above) doesn't have to be explicitly specified in C#, so we can get rid of it:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange(ref _statusMessage, value, "StatusMessage"); }
        }

 

…and why pass the property name when we can get it via reflection? We can make it as simple as this:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange(ref _statusMessage, value); }
        }

 

…with an override to our CheckForPropertyChange method:

        protected bool CheckForPropertyChange<T>(ref T currentValue, T value)
        {
            string propertyName = new StackTrace().GetFrame(1).GetMethod().Name
                .Substring(4); // bypass "set_" prefix
 
            return CheckForPropertyChange(ref currentValue, value, propertyName);
        }

 

(Yes, reflection is slow, but in the context of a ViewModel bound to a Silverlight or WPF "business form" view, I doubt very much that there will be a noticeable difference to the user. Don't use it where performance is really, really important, and when optimizing for performance always measure to confirm your assumptions.)

EDIT: 8/2/2010:
See also: INotifyPropertyChanged with less code using Expressions

Posted on Tuesday, July 27, 2010 8:44 AM .NET | Back to top


Comments on this post: INotifyPropertyChanged with less code using generics & reflection

# re: INotifyPropertyChanged with less code using generics & reflection
Requesting Gravatar...
After looking at a few approaches to get the name of the property being changed, I'd rather use the expression trees to do that.

See the method InvokePropertyChanged in the whole code sample at http://jaylee.org/post/2010/01/02/WinForms-DataBinding-and-Updates-from-multiple-Threads.aspx
Left by Jerome Laban on Jul 27, 2010 8:59 AM

# re: INotifyPropertyChanged with less code using generics & reflection
Requesting Gravatar...
You might want to take a look at the links below as there are some situations where the Stack Trace could be different due to the inlining that the JIT does.

See http://stackoverflow.com/questions/2345957/access-the-stacktrace-when-deploying-in-release-mode and http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx
Left by Matt Warren on Jul 27, 2010 9:29 AM

# re: INotifyPropertyChanged with less code using generics & reflection
Requesting Gravatar...
Thanks, Matt - I'll take a look at it.
Left by Brian Schroer on Jul 27, 2010 9:35 AM

# re: INotifyPropertyChanged with less code using generics & reflection
Requesting Gravatar...
Yea. I would use expression trees as well. It will be much faster than spinning up a stack trace each time.

See MVC does something similar http://aspnet.codeplex.com/SourceControl/changeset/view/23011#266392
Left by Mark Borcherding on Jul 27, 2010 10:04 AM

Your comment:
 (will show your gravatar)


Copyright © Brian Schroer | Powered by: GeeksWithBlogs.net