1+ using System . Collections . Generic ;
2+ using System . Linq . Expressions ;
3+ using System . Reflection ;
4+
5+ public static class MemberExpressionExtractor
6+ {
7+ public static IEnumerable < MemberInfo > GetAllMemberExpressionsMemberInfo ( this Expression expression )
8+ {
9+ var result = new List < MemberInfo > ( ) ;
10+ CollectMemberInfos ( expression , result ) ;
11+ return result ;
12+ }
13+
14+ private static void CollectMemberInfos ( Expression expression , ICollection < MemberInfo > results )
15+ {
16+ if ( expression == null ) return ;
17+
18+ if ( expression is MemberExpression memberExpression )
19+ {
20+ results . Add ( memberExpression . Member ) ;
21+ }
22+ else if ( expression is BinaryExpression binaryExpression && binaryExpression . NodeType == ExpressionType . Assign )
23+ {
24+ ProcessBinaryAssign ( binaryExpression , results ) ;
25+ }
26+
27+ foreach ( var subExpression in expression . GetSubExpressions ( ) )
28+ {
29+ CollectMemberInfos ( subExpression , results ) ;
30+ }
31+ }
32+
33+ private static void ProcessBinaryAssign ( BinaryExpression assignExpression , ICollection < MemberInfo > results )
34+ {
35+ if ( assignExpression == null ) return ;
36+
37+ if ( assignExpression . Left is MemberExpression leftMember )
38+ {
39+ results . Add ( leftMember . Member ) ;
40+ }
41+
42+ CollectMemberInfos ( assignExpression . Right , results ) ;
43+ }
44+
45+ private static IEnumerable < Expression > GetSubExpressions ( this Expression expression )
46+ {
47+ if ( expression == null ) yield break ;
48+
49+ switch ( expression . NodeType )
50+ {
51+ case ExpressionType . MemberAccess :
52+ yield return ( ( MemberExpression ) expression ) . Expression ;
53+ break ;
54+
55+ case ExpressionType . Call :
56+ foreach ( var arg in ( ( MethodCallExpression ) expression ) . Arguments )
57+ yield return arg ;
58+ yield return ( ( MethodCallExpression ) expression ) . Object ;
59+ break ;
60+
61+ case ExpressionType . Lambda :
62+ yield return ( ( LambdaExpression ) expression ) . Body ;
63+ break ;
64+
65+ case ExpressionType . Block :
66+ foreach ( var blockExpr in ( ( BlockExpression ) expression ) . Expressions )
67+ yield return blockExpr ;
68+ break ;
69+
70+ case ExpressionType . Conditional :
71+ yield return ( ( ConditionalExpression ) expression ) . Test ;
72+ yield return ( ( ConditionalExpression ) expression ) . IfTrue ;
73+ yield return ( ( ConditionalExpression ) expression ) . IfFalse ;
74+ break ;
75+
76+ case ExpressionType . NewArrayInit or ExpressionType . NewArrayBounds :
77+ foreach ( var arrayItem in ( ( NewArrayExpression ) expression ) . Expressions )
78+ yield return arrayItem ;
79+ break ;
80+
81+ case ExpressionType . New :
82+ foreach ( var arg in ( ( NewExpression ) expression ) . Arguments )
83+ yield return arg ;
84+ break ;
85+
86+ case ExpressionType . Invoke :
87+ yield return ( ( InvocationExpression ) expression ) . Expression ;
88+ break ;
89+
90+ case ExpressionType . Assign :
91+ yield return ( ( BinaryExpression ) expression ) . Left ;
92+ yield return ( ( BinaryExpression ) expression ) . Right ;
93+ break ;
94+
95+ case ExpressionType . Add :
96+ case ExpressionType . Subtract :
97+ case ExpressionType . Multiply :
98+ case ExpressionType . Divide :
99+ case ExpressionType . Equal :
100+ case ExpressionType . NotEqual :
101+ case ExpressionType . GreaterThan :
102+ case ExpressionType . LessThan :
103+ case ExpressionType . AndAlso :
104+ case ExpressionType . OrElse :
105+ yield return ( ( BinaryExpression ) expression ) . Left ;
106+ yield return ( ( BinaryExpression ) expression ) . Right ;
107+ break ;
108+
109+ case ExpressionType . Not :
110+ case ExpressionType . Negate :
111+ case ExpressionType . Convert :
112+ case ExpressionType . Increment :
113+ case ExpressionType . Decrement :
114+ case ExpressionType . Quote :
115+ case ExpressionType . TypeAs :
116+ case ExpressionType . OnesComplement :
117+ yield return ( ( UnaryExpression ) expression ) . Operand ;
118+ break ;
119+
120+ case ExpressionType . TypeIs :
121+ yield return ( ( TypeBinaryExpression ) expression ) . Expression ;
122+ break ;
123+
124+ case ExpressionType . Coalesce :
125+ yield return ( ( BinaryExpression ) expression ) . Left ;
126+ yield return ( ( BinaryExpression ) expression ) . Conversion ;
127+ yield return ( ( BinaryExpression ) expression ) . Right ;
128+ break ;
129+
130+ case ExpressionType . Index :
131+ yield return ( ( IndexExpression ) expression ) . Object ;
132+ foreach ( var indexArg in ( ( IndexExpression ) expression ) . Arguments )
133+ yield return indexArg ;
134+ break ;
135+
136+ case ExpressionType . Loop :
137+ yield return ( ( LoopExpression ) expression ) . Body ;
138+ break ;
139+
140+ case ExpressionType . Try :
141+ yield return ( ( TryExpression ) expression ) . Body ;
142+ foreach ( var handler in ( ( TryExpression ) expression ) . Handlers )
143+ yield return handler . Body ;
144+ yield return ( ( TryExpression ) expression ) . Finally ;
145+ break ;
146+
147+
148+ default :
149+ break ;
150+ }
151+ }
152+ }
0 commit comments