That's what I mocked as an exercise. Originally inspired by Jon Skeet blog post .
public static class ObjectExtensions { public static string GetPropertyNameAndValue<T>(this T obj, out object value) { System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties(); if(objGetTypeGetProperties.Length == 1) { value = objGetTypeGetProperties[0].GetValue(obj, null); return objGetTypeGetProperties[0].Name; } else throw new ArgumentException("object must contain one property"); } } class Whatever { protected void ChangeProperty<T>(object property, T newValue, Action change) { object value; var name = property.GetPropertyNameAndValue(out value); if(value == null && newValue != null || value != null && !value.Equals(newValue)) { change(); OnPropertyChanged(name); } } private string m_Title; public string Title { get { return m_Title; } set {ChangeProperty( new { Title }, //This is used to dynamically retrieve the property name and value value, // new value () => m_Title = value);
This is the best I could think of. Slow performance at runtime can be quite high, but I have not tested it.
A bit about this explanation. new { Title } creates an anonymous object and because of the project (introduced in .NET 3.5), the newly created object has one Title property and a value that is the value of the Title property of the original object.
GetPropertyNameAndValue is a function that does all the interesting work — it extracts the name and value of a property from an anonymous object. ChangeProperty then performs an equality check and calls the lambda, which actually changes the property, and also calls NotifyPropertyChanged .
Alternatively, you can simply do this snipppp:
<?xml version="1.0" encoding="utf-8" ?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>propfullinotify</Title> <Shortcut>propfullinotify</Shortcut> <Description>Code snippet for property and backing field with INotifyPropertyChanged</Description> <Author>Microsoft Corporation</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> </Header> <Snippet> <Declarations> <Literal> <ID>type</ID> <ToolTip>Property type</ToolTip> <Default>int</Default> </Literal> <Literal> <ID>property</ID> <ToolTip>Property name</ToolTip> <Default>MyProperty</Default> </Literal> <Literal> <ID>field</ID> <ToolTip>The variable backing this property</ToolTip> <Default>myVar</Default> </Literal> </Declarations> <Code Language="csharp"> <![CDATA[private $type$ $field$; public $type$ $property$ { get { return $field$;} set { if ($field$ != value) { $field$ = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("$property$")); } } } $end$]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets>
Igor Zevaka
source share