11using System . Linq . Expressions ;
22using System . Reflection ;
33
4- namespace System . Linq . Dynamic . Core . Parser
4+ namespace System . Linq . Dynamic . Core . Parser ;
5+
6+ /// <summary>
7+ /// ExpressionPromoter
8+ /// </summary>
9+ public class ExpressionPromoter : IExpressionPromoter
510{
11+ private readonly NumberParser _numberParser ;
12+ private readonly ConstantExpressionHelper _constantExpressionHelper ;
13+
614 /// <summary>
7- /// ExpressionPromoter
15+ /// Initializes a new instance of the <see cref=" ExpressionPromoter"/> class.
816 /// </summary>
9- public class ExpressionPromoter : IExpressionPromoter
17+ /// <param name="config">The ParsingConfig.</param>
18+ public ExpressionPromoter ( ParsingConfig config )
1019 {
11- private readonly NumberParser _numberParser ;
12- private readonly ConstantExpressionHelper _constantExpressionHelper ;
20+ _numberParser = new NumberParser ( config ) ;
21+ _constantExpressionHelper = ConstantExpressionHelperFactory . GetInstance ( config ) ;
22+ }
1323
14- /// <summary >
15- /// Initializes a new instance of the <see cref="ExpressionPromoter"/> class.
16- /// </summary>
17- /// <param name="config">The ParsingConfig.</param>
18- public ExpressionPromoter ( ParsingConfig config )
24+ /// <inheritdoc / >
25+ public virtual Expression ? Promote ( Expression sourceExpression , Type type , bool exact , bool convertExpression )
26+ {
27+ Type returnType ;
28+ if ( sourceExpression is LambdaExpression lambdaExpression )
1929 {
20- _numberParser = new NumberParser ( config ) ;
21- _constantExpressionHelper = ConstantExpressionHelperFactory . GetInstance ( config ) ;
30+ returnType = lambdaExpression . GetReturnType ( ) ;
2231 }
23-
24- /// <inheritdoc />
25- public virtual Expression ? Promote ( Expression expr , Type type , bool exact , bool convertExpr )
32+ else
2633 {
27- Type returnType ;
28- if ( expr is LambdaExpression lambdaExpression )
29- {
30- returnType = lambdaExpression . GetReturnType ( ) ;
31- }
32- else
33- {
34- returnType = expr . Type ;
35- }
34+ returnType = sourceExpression . Type ;
35+ }
3636
37- if ( returnType == type || type . IsGenericParameter )
38- {
39- return expr ;
40- }
37+ if ( returnType == type || type . IsGenericParameter )
38+ {
39+ return sourceExpression ;
40+ }
4141
42- if ( expr is ConstantExpression ce )
42+ if ( sourceExpression is ConstantExpression ce )
43+ {
44+ if ( Constants . IsNull ( ce ) )
4345 {
44- if ( Constants . IsNull ( ce ) )
46+ if ( ! type . GetTypeInfo ( ) . IsValueType || TypeHelper . IsNullableType ( type ) )
4547 {
46- if ( ! type . GetTypeInfo ( ) . IsValueType || TypeHelper . IsNullableType ( type ) )
47- {
48- return Expression . Constant ( null , type ) ;
49- }
48+ return Expression . Constant ( null , type ) ;
5049 }
51- else
50+ }
51+ else
52+ {
53+ if ( _constantExpressionHelper . TryGetText ( ce , out var text ) )
5254 {
53- if ( _constantExpressionHelper . TryGetText ( ce , out var text ) )
54- {
55- Type target = TypeHelper . GetNonNullableType ( type ) ;
56- object ? value = null ;
55+ Type target = TypeHelper . GetNonNullableType ( type ) ;
56+ object ? value = null ;
5757
5858#if ! ( UAP10_0 || NETSTANDARD )
59- switch ( Type . GetTypeCode ( ce . Type ) )
60- {
61- case TypeCode . Int32 :
62- case TypeCode . UInt32 :
63- case TypeCode . Int64 :
64- case TypeCode . UInt64 :
65- value = _numberParser . ParseNumber ( text , target ) ;
66-
67- // Make sure an enum value stays an enum value
68- if ( target . IsEnum )
69- {
70- value = Enum . ToObject ( target , value ! ) ;
71- }
72- break ;
73-
74- case TypeCode . Double :
75- if ( target == typeof ( decimal ) || target == typeof ( double ) )
76- {
77- value = _numberParser . ParseNumber ( text , target ) ;
78- }
79- break ;
59+ switch ( Type . GetTypeCode ( ce . Type ) )
60+ {
61+ case TypeCode . Int32 :
62+ case TypeCode . UInt32 :
63+ case TypeCode . Int64 :
64+ case TypeCode . UInt64 :
65+ value = _numberParser . ParseNumber ( text , target ) ;
8066
81- case TypeCode . String :
82- TypeHelper . TryParseEnum ( text , target , out value ) ;
83- break ;
84- }
85- #else
86- if ( ce . Type == typeof ( int ) || ce . Type == typeof ( uint ) || ce . Type == typeof ( long ) || ce . Type == typeof ( ulong ) )
87- {
88- // If target is an enum value, just use the Value from the ConstantExpression
89- if ( target . GetTypeInfo ( ) . IsEnum )
90- {
91- value = Enum . ToObject ( target , ce . Value ) ;
92- }
93- else
67+ // Make sure an enum value stays an enum value
68+ if ( target . IsEnum )
9469 {
95- value = _numberParser . ParseNumber ( text ! , target ) ;
70+ value = Enum . ToObject ( target , value ! ) ;
9671 }
97- }
98- else if ( ce . Type == typeof ( double ) )
99- {
72+ break ;
73+
74+ case TypeCode . Double :
10075 if ( target == typeof ( decimal ) || target == typeof ( double ) )
10176 {
10277 value = _numberParser . ParseNumber ( text , target ) ;
10378 }
79+ break ;
80+
81+ case TypeCode . String :
82+ TypeHelper . TryParseEnum ( text , target , out value ) ;
83+ break ;
84+ }
85+ #else
86+ if ( ce . Type == typeof ( int ) || ce . Type == typeof ( uint ) || ce . Type == typeof ( long ) || ce . Type == typeof ( ulong ) )
87+ {
88+ // If target is an enum value, just use the Value from the ConstantExpression
89+ if ( target . GetTypeInfo ( ) . IsEnum )
90+ {
91+ value = Enum . ToObject ( target , ce . Value ) ;
10492 }
105- else if ( ce . Type == typeof ( string ) && TypeHelper . TryParseEnum ( text , target , out value ) )
93+ else
10694 {
107- // Empty if
95+ value = _numberParser . ParseNumber ( text ! , target ) ;
10896 }
109- #endif
110- if ( value != null )
97+ }
98+ else if ( ce . Type == typeof ( double ) )
99+ {
100+ if ( target == typeof ( decimal ) || target == typeof ( double ) )
111101 {
112- return Expression . Constant ( value , type ) ;
102+ value = _numberParser . ParseNumber ( text , target ) ;
113103 }
114104 }
105+ else if ( ce . Type == typeof ( string ) && TypeHelper . TryParseEnum ( text , target , out value ) )
106+ {
107+ // Empty if
108+ }
109+ #endif
110+ if ( value != null )
111+ {
112+ return Expression . Constant ( value , type ) ;
113+ }
115114 }
116115 }
116+ }
117117
118- if ( TypeHelper . IsCompatibleWith ( returnType , type ) )
118+ if ( TypeHelper . IsCompatibleWith ( returnType , type ) )
119+ {
120+ if ( type == typeof ( decimal ) && TypeHelper . IsEnumType ( sourceExpression . Type ) )
119121 {
120- if ( type == typeof ( decimal ) && TypeHelper . IsEnumType ( expr . Type ) )
121- {
122- return Expression . Convert ( Expression . Convert ( expr , Enum . GetUnderlyingType ( expr . Type ) ) , type ) ;
123- }
124-
125- if ( type . GetTypeInfo ( ) . IsValueType || exact || expr . Type . GetTypeInfo ( ) . IsValueType && convertExpr )
126- {
127- return Expression . Convert ( expr , type ) ;
128- }
122+ return Expression . Convert ( Expression . Convert ( sourceExpression , Enum . GetUnderlyingType ( sourceExpression . Type ) ) , type ) ;
123+ }
129124
130- return expr ;
125+ if ( type . GetTypeInfo ( ) . IsValueType || exact || sourceExpression . Type . GetTypeInfo ( ) . IsValueType && convertExpression )
126+ {
127+ return Expression . Convert ( sourceExpression , type ) ;
131128 }
132129
133- return null ;
130+ return sourceExpression ;
134131 }
132+
133+ return null ;
135134 }
136135}
0 commit comments