@@ -22,49 +22,51 @@ public static IEnumerable<MemberExpression> GetMembers<TObject, TProperty>(this
2222 }
2323 }
2424
25- internal static Func < object , IObservable < Unit > > CreatePropertyChangedFactory ( this MemberExpression source )
25+ internal static Func < object , IObservable < Unit > > CreatePropertyChangedFactory ( this Expression source )
2626 {
27- var property = source . GetProperty ( ) ;
28-
29- if ( property . DeclaringType is null )
27+ if ( ( source is not MemberExpression { Member : PropertyInfo property } )
28+ || ! typeof ( INotifyPropertyChanged ) . IsAssignableFrom ( property . DeclaringType ) )
3029 {
31- throw new ArgumentException ( "The property does not have a valid declaring type." , nameof ( source ) ) ;
30+ return static _ => Observable . Never < Unit > ( ) ;
3231 }
3332
34- var notifyPropertyChanged = typeof ( INotifyPropertyChanged ) . GetTypeInfo ( ) . IsAssignableFrom ( property . DeclaringType . GetTypeInfo ( ) ) ;
35-
36- return t => ( ( t is null ) || ! notifyPropertyChanged )
37- ? Observable < Unit > . Never
38-
39- : Observable . FromEventPattern < PropertyChangedEventHandler , PropertyChangedEventArgs > ( handler => ( ( INotifyPropertyChanged ) t ) . PropertyChanged += handler , handler => ( ( INotifyPropertyChanged ) t ) . PropertyChanged -= handler ) . Where ( args => args . EventArgs . PropertyName == property . Name ) . Select ( _ => Unit . Default ) ;
33+ return target => Observable . FromEventPattern < PropertyChangedEventHandler , PropertyChangedEventArgs > (
34+ addHandler : handler => ( ( INotifyPropertyChanged ) target ) . PropertyChanged += handler ,
35+ removeHandler : handler => ( ( INotifyPropertyChanged ) target ) . PropertyChanged -= handler )
36+ . Where ( pattern => pattern . EventArgs . PropertyName == property . Name )
37+ . Select ( static _ => Unit . Default ) ;
4038 }
4139
42- internal static Func < object , object > CreateValueAccessor ( this MemberExpression source )
40+ internal static Func < object , object ? > CreateInvoker ( this Expression source )
4341 {
44- // create an expression which accepts the parent and returns the child
45- var property = source . GetProperty ( ) ;
46- var method = property . GetMethod ;
47-
48- if ( method is null )
42+ switch ( source )
4943 {
50- throw new ArgumentException ( "The property does not have a valid get method." , nameof ( method ) ) ;
51- }
44+ case MemberExpression memberExpression :
45+ if ( memberExpression . Member is not PropertyInfo property )
46+ throw new ArgumentException ( $ "Unable to parse expression: Member type { memberExpression . Member . MemberType } is not supported", nameof ( source ) ) ;
5247
53- if ( source . Expression is null )
54- {
55- throw new ArgumentException ( "The source expression does not have a valid expression." , nameof ( source ) ) ;
56- }
48+ if ( property . GetMethod is null )
49+ throw new ArgumentException ( $ "Unable to parse expression: Property \" { property . Name } \" has no getter", nameof ( source ) ) ;
50+
51+ if ( property . GetMethod . IsStatic )
52+ throw new ArgumentException ( $ "Unable to parse expression: Property \" { property . Name } \" is static", nameof ( source ) ) ;
53+
54+ return property . GetValue ;
5755
58- // convert the parameter i.e. the declaring class to an object
59- var parameter = Expression . Parameter ( typeof ( object ) ) ;
60- var converted = Expression . Convert ( parameter , source . Expression . Type ) ;
56+ case UnaryExpression { NodeType : ExpressionType . Convert } convertExpression :
57+ return ( convertExpression . Type . IsGenericType
58+ && ( convertExpression . Type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) ) )
59+ ? static target => target
60+ : target => Convert . ChangeType (
61+ value : target ,
62+ conversionType : convertExpression . Type ) ;
6163
62- // call the get value of the property and box it
63- var propertyCall = Expression . Call ( converted , method ) ;
64- var boxed = Expression . Convert ( propertyCall , typeof ( object ) ) ;
65- var accessorExpr = Expression . Lambda < Func < object , object > > ( boxed , parameter ) ;
64+ case null :
65+ throw new ArgumentNullException ( nameof ( source ) ) ;
6666
67- return accessorExpr . Compile ( ) ;
67+ default :
68+ throw new ArgumentException ( $ "Unable to parse expression: Node type { source . NodeType } not supported", nameof ( source ) ) ;
69+ }
6870 }
6971
7072 internal static MemberInfo GetMember < TObject , TProperty > ( this Expression < Func < TObject , TProperty > > expression )
@@ -77,22 +79,29 @@ internal static MemberInfo GetMember<TObject, TProperty>(this Expression<Func<TO
7779 return GetMemberInfo ( expression ) ;
7880 }
7981
80- internal static IEnumerable < MemberExpression > GetMemberChain < TObject , TProperty > ( this Expression < Func < TObject , TProperty > > expression )
82+ internal static IEnumerable < Expression > SplitIntoSteps < TObject , TProperty > ( this Expression < Func < TObject , TProperty > > expression )
8183 {
82- var memberExpression = expression . Body as MemberExpression ;
83- while ( memberExpression ? . Expression is not null )
84+ var currentStep = expression . Body ;
85+ while ( currentStep is not null )
8486 {
85- if ( memberExpression . Expression . NodeType != ExpressionType . Parameter )
86- {
87- var parent = memberExpression . Expression ;
88- yield return memberExpression . Update ( Expression . Parameter ( parent . Type ) ) ;
89- }
90- else
87+ switch ( currentStep )
9188 {
92- yield return memberExpression ;
93- }
89+ case MemberExpression memberExpression :
90+ yield return memberExpression ;
91+ currentStep = memberExpression . Expression ;
92+ break ;
9493
95- memberExpression = memberExpression . Expression as MemberExpression ;
94+ case ParameterExpression :
95+ yield break ;
96+
97+ case UnaryExpression { NodeType : ExpressionType . Convert } unaryExpression :
98+ yield return unaryExpression ;
99+ currentStep = unaryExpression . Operand ;
100+ break ;
101+
102+ default :
103+ throw new ArgumentException ( $ "Unable to parse expression: Node type { currentStep . NodeType } is not supported", nameof ( expression ) ) ;
104+ }
96105 }
97106 }
98107
0 commit comments