Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save deerwood-mccord-jr/03e277091525d7cb3026e1aaa3ff63a5 to your computer and use it in GitHub Desktop.
Save deerwood-mccord-jr/03e277091525d7cb3026e1aaa3ff63a5 to your computer and use it in GitHub Desktop.
INotifyPropertyChangedLambda
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