using System; using System.ComponentModel; using System.Linq.Expressions; using System.Reactive.Linq; using System.Reflection; namespace MiniMvvm { public static class PropertyChangedExtensions { class PropertyObservable : IObservable { private readonly INotifyPropertyChanged _target; private readonly PropertyInfo _info; public PropertyObservable(INotifyPropertyChanged target, PropertyInfo info) { _target = target; _info = info; } class Subscription : IDisposable { private readonly INotifyPropertyChanged _target; private readonly PropertyInfo _info; private readonly IObserver _observer; public Subscription(INotifyPropertyChanged target, PropertyInfo info, IObserver observer) { _target = target; _info = info; _observer = observer; _target.PropertyChanged += OnPropertyChanged; _observer.OnNext((T)_info.GetValue(_target)); } private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == _info.Name) _observer.OnNext((T)_info.GetValue(_target)); } public void Dispose() { _target.PropertyChanged -= OnPropertyChanged; _observer.OnCompleted(); } } public IDisposable Subscribe(IObserver observer) { return new Subscription(_target, _info, observer); } } public static IObservable WhenAnyValue(this TModel model, Expression> expr) where TModel : INotifyPropertyChanged { var l = (LambdaExpression)expr; var ma = (MemberExpression)l.Body; var prop = (PropertyInfo)ma.Member; return new PropertyObservable(model, prop); } public static IObservable WhenAnyValue(this TModel model, Expression> v1, Func cb ) where TModel : INotifyPropertyChanged { return model.WhenAnyValue(v1).Select(cb); } public static IObservable WhenAnyValue(this TModel model, Expression> v1, Expression> v2, Func cb ) where TModel : INotifyPropertyChanged => Observable.CombineLatest( model.WhenAnyValue(v1), model.WhenAnyValue(v2), cb); public static IObservable> WhenAnyValue(this TModel model, Expression> v1, Expression> v2 ) where TModel : INotifyPropertyChanged => model.WhenAnyValue(v1, v2, (a1, a2) => (a1, a2)); public static IObservable WhenAnyValue(this TModel model, Expression> v1, Expression> v2, Expression> v3, Func cb ) where TModel : INotifyPropertyChanged => Observable.CombineLatest( model.WhenAnyValue(v1), model.WhenAnyValue(v2), model.WhenAnyValue(v3), cb); public static IObservable> WhenAnyValue(this TModel model, Expression> v1, Expression> v2, Expression> v3 ) where TModel : INotifyPropertyChanged => model.WhenAnyValue(v1, v2, v3, (a1, a2, a3) => (a1, a2, a3)); } }