@@ -35,7 +35,39 @@ public static IObservable<TReturn> WhenPropertyValueChanges<TObj, TReturn>(
35
35
throw new ArgumentNullException ( nameof ( propertyExpression ) ) ;
36
36
}
37
37
38
- return WhenPropertyChanges ( objectToMonitor , propertyExpression ) . Select ( x => x . Value ) ;
38
+ IObservable < INotifyPropertyChanged > currentObservable = Observable . Return ( ( INotifyPropertyChanged ) objectToMonitor ) ;
39
+
40
+ var expressionChain = propertyExpression . Body . GetExpressionChain ( ) ;
41
+
42
+ if ( expressionChain . Count == 0 )
43
+ {
44
+ throw new ArgumentException ( "There are no properties in the expressions" , nameof ( propertyExpression ) ) ;
45
+ }
46
+
47
+ var i = 0 ;
48
+ foreach ( var memberExpression in expressionChain )
49
+ {
50
+ var memberInfo = memberExpression . Member ;
51
+
52
+ if ( i == expressionChain . Count - 1 )
53
+ {
54
+ return Observable . Return ( memberInfo )
55
+ . CombineLatest ( currentObservable , ( memberInfo , parent ) => ( memberInfo , value : parent ) )
56
+ . Where ( x => x . value != null )
57
+ . Select ( x => GenerateObservable ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , TReturn > . GetCache ( x . memberInfo ) ) )
58
+ . Switch ( ) ;
59
+ }
60
+
61
+ currentObservable = Observable . Return ( memberInfo )
62
+ . CombineLatest ( currentObservable , ( memberInfo , parent ) => ( memberInfo , value : parent ) )
63
+ . Where ( x => x . value != null )
64
+ . Select ( x => GenerateObservable ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , INotifyPropertyChanged > . GetCache ( x . memberInfo ) ) )
65
+ . Switch ( ) ;
66
+
67
+ i ++ ;
68
+ }
69
+
70
+ throw new ArgumentException ( "Invalid expression" , nameof ( propertyExpression ) ) ;
39
71
}
40
72
41
73
/// <summary>
@@ -77,14 +109,14 @@ public static IObservable<TReturn> WhenPropertyValueChanges<TObj, TReturn>(
77
109
return Observable . Return ( memberInfo )
78
110
. CombineLatest ( currentObservable , ( memberInfo , parent ) => ( memberInfo , sender : parent . Sender , value : parent . Value ) )
79
111
. Where ( x => x . value != null )
80
- . Select ( x => GenerateObservable ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , TReturn > . GetCache ( x . memberInfo ) ) )
112
+ . Select ( x => GenerateObservableWithSender ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , TReturn > . GetCache ( x . memberInfo ) ) )
81
113
. Switch ( ) ;
82
114
}
83
115
84
116
currentObservable = Observable . Return ( memberInfo )
85
117
. CombineLatest ( currentObservable , ( memberInfo , parent ) => ( memberInfo , sender : parent . Sender , value : parent . Value ) )
86
118
. Where ( x => x . value != null )
87
- . Select ( x => GenerateObservable ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , INotifyPropertyChanged > . GetCache ( x . memberInfo ) ) )
119
+ . Select ( x => GenerateObservableWithSender ( x . value , x . memberInfo , GetMemberFuncCache < INotifyPropertyChanged , INotifyPropertyChanged > . GetCache ( x . memberInfo ) ) )
88
120
. Switch ( ) ;
89
121
90
122
i ++ ;
@@ -93,22 +125,51 @@ public static IObservable<TReturn> WhenPropertyValueChanges<TObj, TReturn>(
93
125
throw new ArgumentException ( "Invalid expression" , nameof ( propertyExpression ) ) ;
94
126
}
95
127
96
- private static IObservable < ( object Sender , T Value ) > GenerateObservable < T > (
128
+ private static IObservable < T > GenerateObservable < T > (
97
129
INotifyPropertyChanged parent ,
98
130
MemberInfo memberInfo ,
99
131
Func < INotifyPropertyChanged , T > getter )
100
132
{
101
133
var memberName = memberInfo . Name ;
102
- return Observable . FromEvent < PropertyChangedEventHandler , ( object Sender , PropertyChangedEventArgs Args ) > (
134
+ return Observable . FromEvent < PropertyChangedEventHandler , T > (
103
135
handler =>
104
136
{
105
- void Handler ( object sender , PropertyChangedEventArgs e ) => handler ( ( sender , e ) ) ;
137
+ void Handler ( object sender , PropertyChangedEventArgs e )
138
+ {
139
+ if ( e . PropertyName == memberName )
140
+ {
141
+ handler ( getter ( parent ) ) ;
142
+ }
143
+ }
144
+
145
+ return Handler ;
146
+ } ,
147
+ x => parent . PropertyChanged += x ,
148
+ x => parent . PropertyChanged -= x )
149
+ . StartWith ( getter ( parent ) ) ;
150
+ }
151
+
152
+ private static IObservable < ( object Sender , T Value ) > GenerateObservableWithSender < T > (
153
+ INotifyPropertyChanged parent ,
154
+ MemberInfo memberInfo ,
155
+ Func < INotifyPropertyChanged , T > getter )
156
+ {
157
+ var memberName = memberInfo . Name ;
158
+ return Observable . FromEvent < PropertyChangedEventHandler , ( object Sender , T Value ) > (
159
+ handler =>
160
+ {
161
+ void Handler ( object sender , PropertyChangedEventArgs e )
162
+ {
163
+ if ( e . PropertyName == memberName )
164
+ {
165
+ handler ( ( sender , getter ( parent ) ) ) ;
166
+ }
167
+ }
168
+
106
169
return Handler ;
107
170
} ,
108
171
x => parent . PropertyChanged += x ,
109
172
x => parent . PropertyChanged -= x )
110
- . Where ( x => x . Args . PropertyName == memberName )
111
- . Select ( x => ( x . Sender , getter ( parent ) ) )
112
173
. StartWith ( ( parent , getter ( parent ) ) ) ;
113
174
}
114
175
}
0 commit comments