Last active
February 18, 2024 18:29
-
-
Save ahmedalejo/68098409b7c5f1ed6068710095c415af to your computer and use it in GitHub Desktop.
INotifyPropertyChanged Reactive Extensions
This file contains hidden or 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
/* Originally from https://github.com/ahmedalejo/System.Reactive.EventStream/blob/master/src/Extensions/INotifyPropertyChangedExtensions.cs */ | |
// Sample Usage | |
component | |
.ObservePropertyChangedValues(component => component.UXScore) | |
.Throttle(TimeSpan.FromSeconds(1)) | |
.Subscribe(uXScore => Console.WriteLine($"Component's UX-Score is currently '{uxScore}'")); | |
component | |
.ObservePropertyChangedValues() | |
.Throttle(TimeSpan.FromSeconds(1)) | |
.Subscribe((name, value) => Console.WriteLine($"Component's {name} is currently '{value}'")); | |
public static class INotifyPropertyChangedExtensions | |
{ | |
/// <summary> | |
/// Observes property changes on a <see cref="INotifyPropertyChanged"/> <see cref="object"/> | |
/// when the value of the property specified by <paramref name="property"/> is changes | |
/// </summary> | |
/// <typeparam name="T">Type of the <see cref="INotifyPropertyChanged"/></typeparam> | |
/// <param name="notifier">The <see cref="object"/> implementing the <see cref="INotifyPropertyChanged"/></param> | |
public static IObservable<Unit> ObservePropertyChanges<T>(this T notifier, string property) | |
where T : INotifyPropertyChanged => | |
notifier.ObservePropertyChangedEvents(property: property) | |
.Select(x => Unit.Default); | |
/// <summary> | |
/// Observes property changes on a <see cref="INotifyPropertyChanged"/> <see cref="object"/> | |
/// returning the value of the property specified by <paramref name="property"/> | |
/// </summary> | |
/// <typeparam name="T">Type of the <see cref="INotifyPropertyChanged"/></typeparam> | |
/// <typeparam name="TProperty">Type of the property to monitor</typeparam> | |
/// <param name="notifier">The <see cref="object"/> implementing the <see cref="INotifyPropertyChanged"/></param> | |
/// <param name="property">The property selector <see cref=" Expression{Func{T,TProperty}}"/></param> | |
public static IObservable<Unit> ObservePropertyChanges<T, TProperty>( | |
this T notifier, | |
Expression<Func<T, TProperty>> property) | |
where T : INotifyPropertyChanged | |
{ | |
if (!(property.Body is MemberExpression body)) | |
throw new ArgumentException("'expression' should be a member expression"); | |
var propertyName = body.Member.Name; | |
return notifier.ObservePropertyChangedEvents(property: propertyName) | |
.Select(x => Unit.Default); | |
} | |
/// <summary> | |
/// Observes property changes on a <see cref="INotifyPropertyChanged"/> <see cref="object"/> | |
/// returning the (name and value) of the property as <see cref="Tuple{string, object}"/> | |
/// </summary> | |
/// <typeparam name="T">Type of the <see cref="INotifyPropertyChanged"/></typeparam> | |
/// <param name="notifier">The <see cref="object"/> implementing the <see cref="INotifyPropertyChanged"/></param> | |
public static IObservable<(string Name, object Value)> ObservePropertyChangedValues<T>( | |
this T notifier) | |
where T : INotifyPropertyChanged | |
{ | |
var propertyGetter = (Func<string, PropertyInfo>)notifier.GetType().GetProperty; | |
return notifier.ObservePropertyChanges() | |
.Select(name => (name, propertyGetter(name)?.GetValue(notifier))); | |
} | |
/// <summary> | |
/// Observes property changes on a <see cref="INotifyPropertyChanged"/> <see cref="object"/> | |
/// returning the value of the property specified by <paramref name="property"/> | |
/// </summary> | |
/// <typeparam name="T">Type of the <see cref="INotifyPropertyChanged"/></typeparam> | |
/// <typeparam name="TProperty">Type of the property to monitor</typeparam> | |
/// <param name="notifier">The <see cref="object"/> implementing the <see cref="INotifyPropertyChanged"/></param> | |
/// <param name="property">The property selector <see cref=" Expression{TDelegate}"/></param> | |
public static IObservable<TProperty> ObservePropertyChangedValues<T, TProperty>( | |
this T notifier, | |
Expression<Func<T, TProperty>> property) | |
where T : INotifyPropertyChanged | |
{ | |
var body = property.Body as MemberExpression; | |
if (body is null) | |
throw new ArgumentException("'expression' should be a member expression"); | |
var propertyName = body.Member.Name; | |
var invoker = (Func<T, TProperty>)property.Compile().Invoke; | |
return notifier.ObservePropertyChangedEvents(property: propertyName) | |
.Select(x => invoker(notifier)); | |
} | |
public static IObservable<PropertyChangedEventArgs> ObservePropertyChangedEvents<T>(this T notifier) | |
where T : INotifyPropertyChanged => | |
Observable.FromEventPattern<PropertyChangedEventArgs>( | |
target: notifier, | |
eventName: nameof(INotifyPropertyChanged.PropertyChanged)) | |
.Select(e => e.EventArgs); | |
public static IObservable<PropertyChangedEventArgs> ObservePropertyChangedEvents<T>(this T notifier, string property) | |
where T : INotifyPropertyChanged => | |
notifier.ObservePropertyChangedEvents() | |
.Where(e => e.PropertyName == property); | |
public static IObservable<string> ObservePropertyChanges<T>(this T notifier) | |
where T : INotifyPropertyChanged => | |
notifier.ObservePropertyChangedEvents() | |
.Select(e => e.PropertyName); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment