Skip to content

Instantly share code, notes, and snippets.

@earthengine
Created November 3, 2016 01:52
Show Gist options
  • Save earthengine/9a5c660bb381b911b000c07a3298707d to your computer and use it in GitHub Desktop.
Save earthengine/9a5c660bb381b911b000c07a3298707d to your computer and use it in GitHub Desktop.
public static class NotificationExtensions
{
private static string PropertyFromMemberExpression(MemberExpression memberExpression)
{
var pinfo = memberExpression.Member as PropertyInfo;
if (pinfo != null)
{
return pinfo.Name;
}
var finfo = memberExpression.Member as FieldInfo;
if (finfo != null)
{
return finfo.Name;
}
return null;
}
/// <summary>
/// Usage
/// //Single property
/// PropertyNamesForExpression&lt;MyObject&gt;(x => x.MyProperty); // returns ["MyProperty"]
/// //Multiple properties
/// //PropertyNamesForExpression&lt;MyObject&gt;(x => new { x.MyProperty1, x.MyProperty2 }); // returns ["MyProperty1","MyProperty2"]
/// </summary>
/// <typeparam name="TObject">Type of objest with property of field</typeparam>
/// <param name="propertyExpression">Expression that access properties of a given object. Can be a simple property/field access or a
/// new anonymous class statement.</param>
/// <returns></returns>
public static IEnumerable<string> PropertyNamesFromExpression<TObject>(Expression<Func<TObject, object>> propertyExpression)
{
var lambda = propertyExpression as LambdaExpression;
var newexp = lambda.Body as NewExpression;
if (newexp == null)
{
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
if (memberExpression == null) yield break;
var result = PropertyFromMemberExpression(memberExpression);
if (result != null) yield return result;
yield break;
};
foreach (var arg in newexp.Arguments)
{
var memberExpression = arg as MemberExpression;
if (memberExpression == null) continue;
var result = PropertyFromMemberExpression(memberExpression);
if (result == null) continue;
yield return result;
}
}
/// <summary>
/// Add a handler for specific property changed event. Can specify a set of properties to be processed
/// </summary>
/// <typeparam name="TNotifier">The type of object that have properties changed</typeparam>
/// <param name="notifier">The object that have properties changed</param>
/// <param name="propertyExpression">
/// Property access expression, can be a single field/property access lambda,
/// or a lambda returns a new anonymous object that contains all properties interested
/// </param>
/// <param name="handler">The handler action</param>
public static void SubscribeToChanges<TNotifier>(this TNotifier notifier, Expression<Func<TNotifier, object>> propertyExpression,
Action<TNotifier> handler) where TNotifier : INotifyPropertyChanged
{
var propertyNames = PropertyNamesFromExpression(propertyExpression);
notifier.PropertyChanged +=
(s, e) =>
{
if (propertyNames.Contains(e.PropertyName) || string.IsNullOrEmpty(e.PropertyName))
{
handler(notifier);
}
};
}
/// <summary>
/// Given an action to raise the property changed event, iterate throw a set of properties, calls the action for each properties.
/// </summary>
/// <typeparam name="TNotifier">The type of object to notify</typeparam>
/// <param name="notifier"></param>
/// <param name="propertyExpression"></param>
/// <param name="notifyChangeDelegate"></param>
public static void RaisePropertiesChanged<TNotifier>(this TNotifier notifier, Expression<Func<TNotifier, object>> propertyExpression
, Action<string> notifyChangeDelegate)
{
foreach (var name in PropertyNamesFromExpression(propertyExpression))
{
notifyChangeDelegate(name);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment