PropertyChangedExtensions.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using System.ComponentModel;
  3. using System.Linq.Expressions;
  4. using System.Reflection;
  5. using Avalonia.Reactive;
  6. namespace MiniMvvm
  7. {
  8. public static class PropertyChangedExtensions
  9. {
  10. class PropertyObservable<T> : IObservable<T>
  11. {
  12. private readonly INotifyPropertyChanged _target;
  13. private readonly PropertyInfo _info;
  14. public PropertyObservable(INotifyPropertyChanged target, PropertyInfo info)
  15. {
  16. _target = target;
  17. _info = info;
  18. }
  19. class Subscription : IDisposable
  20. {
  21. private readonly INotifyPropertyChanged _target;
  22. private readonly PropertyInfo _info;
  23. private readonly IObserver<T> _observer;
  24. public Subscription(INotifyPropertyChanged target, PropertyInfo info, IObserver<T> observer)
  25. {
  26. _target = target;
  27. _info = info;
  28. _observer = observer;
  29. _target.PropertyChanged += OnPropertyChanged;
  30. _observer.OnNext((T)_info.GetValue(_target));
  31. }
  32. private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
  33. {
  34. if (e.PropertyName == _info.Name)
  35. _observer.OnNext((T)_info.GetValue(_target));
  36. }
  37. public void Dispose()
  38. {
  39. _target.PropertyChanged -= OnPropertyChanged;
  40. _observer.OnCompleted();
  41. }
  42. }
  43. public IDisposable Subscribe(IObserver<T> observer)
  44. {
  45. return new Subscription(_target, _info, observer);
  46. }
  47. }
  48. public static IObservable<TRes> WhenAnyValue<TModel, TRes>(this TModel model,
  49. Expression<Func<TModel, TRes>> expr) where TModel : INotifyPropertyChanged
  50. {
  51. var l = (LambdaExpression)expr;
  52. var ma = (MemberExpression)l.Body;
  53. var prop = (PropertyInfo)ma.Member;
  54. return new PropertyObservable<TRes>(model, prop);
  55. }
  56. public static IObservable<TRes> WhenAnyValue<TModel, T1, TRes>(this TModel model,
  57. Expression<Func<TModel, T1>> v1,
  58. Func<T1, TRes> cb
  59. ) where TModel : INotifyPropertyChanged
  60. {
  61. return model.WhenAnyValue(v1).Select(cb);
  62. }
  63. public static IObservable<TRes> WhenAnyValue<TModel, T1, T2, TRes>(this TModel model,
  64. Expression<Func<TModel, T1>> v1,
  65. Expression<Func<TModel, T2>> v2,
  66. Func<T1, T2, TRes> cb
  67. ) where TModel : INotifyPropertyChanged =>
  68. Observable.CombineLatest(
  69. model.WhenAnyValue(v1),
  70. model.WhenAnyValue(v2),
  71. cb);
  72. public static IObservable<ValueTuple<T1, T2>> WhenAnyValue<TModel, T1, T2>(this TModel model,
  73. Expression<Func<TModel, T1>> v1,
  74. Expression<Func<TModel, T2>> v2
  75. ) where TModel : INotifyPropertyChanged =>
  76. model.WhenAnyValue(v1, v2, (a1, a2) => (a1, a2));
  77. public static IObservable<TRes> WhenAnyValue<TModel, T1, T2, T3, TRes>(this TModel model,
  78. Expression<Func<TModel, T1>> v1,
  79. Expression<Func<TModel, T2>> v2,
  80. Expression<Func<TModel, T3>> v3,
  81. Func<T1, T2, T3, TRes> cb
  82. ) where TModel : INotifyPropertyChanged =>
  83. model.WhenAnyValue(v1)
  84. .CombineLatest(
  85. model.WhenAnyValue(v2),
  86. (l, r) => (l, r))
  87. .CombineLatest(
  88. model.WhenAnyValue(v3),
  89. (t, r) => cb(t.l, t.r, r));
  90. public static IObservable<ValueTuple<T1, T2, T3>> WhenAnyValue<TModel, T1, T2, T3>(this TModel model,
  91. Expression<Func<TModel, T1>> v1,
  92. Expression<Func<TModel, T2>> v2,
  93. Expression<Func<TModel, T3>> v3
  94. ) where TModel : INotifyPropertyChanged =>
  95. model.WhenAnyValue(v1, v2, v3, (a1, a2, a3) => (a1, a2, a3));
  96. }
  97. }