Created
April 10, 2018 15:28
-
-
Save deerwood-mccord-jr/03e277091525d7cb3026e1aaa3ff63a5 to your computer and use it in GitHub Desktop.
INotifyPropertyChangedLambda
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Sagentia.PgxGss.MainGuiDll.Support | |
{ | |
public interface INotifyPropertyChangedLambda : INotifyPropertyChanged | |
{ | |
void OnPropertyChanged(string caller); | |
Dictionary<string, object> PropertyValueStorage { get; } | |
} | |
// Inspired by http://dotnet-forum.de/blogs/thearchitect/archive/2012/11/01/die-optimale-implementierung-des-inotifypropertychanged-interfaces.aspx | |
// and http://stackoverflow.com/questions/2059411/expression-tree-how-to-get-at-declaring-instance | |
public static class NotifyPropertyChangedLambdaExtension | |
{ | |
/// <summary> | |
/// Set the value of the property and raise the [PropertyChanged] event | |
/// (only if the saved value and the new value are not equal). | |
/// Usage: set { SetValue(() => PropertyName, value); } | |
/// </summary> | |
/// <typeparam name="T">The property type</typeparam> | |
/// <param name="property">The property as a lambda expression</param> | |
/// <param name="value">The new value of the property</param> | |
public static void SetProperty<T>(this INotifyPropertyChangedLambda obj, Expression<Func<T>> property, T value) | |
{ | |
LambdaExpression lambdaExpression = property as LambdaExpression; | |
if (lambdaExpression == null) | |
throw new ArgumentException("property"); | |
string propertyName = GetPropertyName(lambdaExpression); | |
T storedValue = getValue<T>(obj, propertyName); | |
if (!object.Equals(storedValue, value)) | |
{ | |
obj.PropertyValueStorage[propertyName] = value; | |
obj.OnPropertyChanged(propertyName); | |
} | |
} | |
/// <summary> | |
/// Get the value of a property | |
/// Usage: get { return GetValue(() => PropertyName); } | |
/// </summary> | |
/// <typeparam name="T">The property type</typeparam> | |
/// <param name="property">The property as a lambda expression</param> | |
/// <returns>The value of the given property (or the default value)</returns> | |
public static T GetProperty<T>(this INotifyPropertyChangedLambda obj, Expression<Func<T>> property) | |
{ | |
LambdaExpression lambdaExpression = property as LambdaExpression; | |
if (lambdaExpression == null) | |
throw new ArgumentException("property"); | |
return getValue<T>(obj, GetPropertyName(lambdaExpression)); | |
} | |
/// <summary> | |
/// Try to get the value from the internal dictionary of the given property name | |
/// </summary> | |
/// <typeparam name="T">The property type</typeparam> | |
/// <param name="propertyName">The name of the property</param> | |
/// <returns>Retrieve the value from the internal dictionary</returns> | |
private static T getValue<T>(INotifyPropertyChangedLambda obj, string propertyName) | |
{ | |
object value; | |
if (obj.PropertyValueStorage.TryGetValue(propertyName, out value)) | |
return (T)value; | |
else | |
return default(T); | |
} | |
/// <summary> | |
/// Extract the property name from a lambda expression | |
/// </summary> | |
/// <param name="lambdaExpression">The lambda expression with the property</param> | |
/// <returns>The extracted property name</returns> | |
public static string GetPropertyName(LambdaExpression lambdaExpression) | |
{ | |
if (lambdaExpression.Body is UnaryExpression) | |
return ((lambdaExpression.Body as UnaryExpression).Operand as MemberExpression).Member.Name; | |
else | |
return (lambdaExpression.Body as MemberExpression).Member.Name; | |
} | |
public static INotifyPropertyChangedLambda GetPropertyObject(LambdaExpression lambdaExpression) | |
{ | |
MemberExpression body; | |
if (lambdaExpression.Body is UnaryExpression) | |
body = (lambdaExpression.Body as UnaryExpression).Operand as MemberExpression; | |
else | |
body = lambdaExpression.Body as MemberExpression; | |
// TODO: Better way of doing this? | |
return Expression.Lambda<Func<INotifyPropertyChangedLambda>>(body.Expression).Compile()(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment