@@ -28,11 +28,11 @@ internal static partial class ObjectExtensions
28
28
try
29
29
{
30
30
// Build the property access expression chain with runtime type checking
31
- var parameterObj = Expression . Parameter ( typeof ( object ) , "obj" ) ; ;
32
- var propertyAccess = BuildPropertyPathExpression ( parameterObj , bindingPath , dataItem ) ;
31
+ var parameterObj = Expression . Parameter ( typeof ( object ) , "obj" ) ;
32
+ var propertyAccess = BuildPropertyPathExpressionTree ( parameterObj , bindingPath , dataItem ) ;
33
33
34
34
// Compile the lambda expression
35
- var lambda = Expression . Lambda < Func < object , object ? > > ( propertyAccess , parameterObj ) ;
35
+ var lambda = Expression . Lambda < Func < object , object ? > > ( Expression . Convert ( propertyAccess , typeof ( object ) ) , parameterObj ) ;
36
36
var _compiledPropertyPath = lambda . Compile ( ) ;
37
37
return _compiledPropertyPath ;
38
38
}
@@ -50,7 +50,7 @@ internal static partial class ObjectExtensions
50
50
/// <param name="bindingPath">The binding path to access.</param>
51
51
/// <param name="dataItem">The actual data item to use for runtime type evaluation, to help with any needed subclass type conversions.</param>
52
52
/// <returns>An expression that accesses the binding path from the </returns>
53
- private static Expression BuildPropertyPathExpression ( ParameterExpression parameterObj , string bindingPath , object dataItem )
53
+ private static Expression BuildPropertyPathExpressionTree ( ParameterExpression parameterObj , string bindingPath , object dataItem )
54
54
{
55
55
Expression current = parameterObj ;
56
56
@@ -80,15 +80,15 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
80
80
else
81
81
{
82
82
// Try to find an indexer property, with an int parameter
83
- var indexerProperty = current . Type . GetProperty ( "Item" , new [ ] { typeof ( int ) } )
83
+ var indexerProperty = current . Type . GetProperty ( "Item" , [ typeof ( int ) ] )
84
84
?? throw new ArgumentException ( $ "Type '{ current . Type . Name } ' does not support integer indexing") ;
85
85
current = Expression . Property ( current , indexerProperty , Expression . Constant ( index ) ) ;
86
86
}
87
87
}
88
88
else
89
89
{
90
90
// Try to find an indexer property, with an string parameter
91
- var indexerProperty = current . Type . GetProperty ( "Item" , new [ ] { typeof ( string ) } )
91
+ var indexerProperty = current . Type . GetProperty ( "Item" , [ typeof ( string ) ] )
92
92
?? throw new ArgumentException ( $ "Type '{ current . Type . Name } ' does not support string indexing") ;
93
93
current = Expression . Property ( current , indexerProperty , Expression . Constant ( stringIndex ) ) ;
94
94
}
@@ -101,8 +101,8 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
101
101
current = Expression . Property ( current , propertyInfo ) ;
102
102
}
103
103
104
- // Compile a lambda of the partial expression thus far, to see if we need to add a cast
105
- var lambdaTemp = Expression . Lambda < Func < object , object ? > > ( current , parameterObj ) ;
104
+ // Compile a lambda of the partial expression thus far (cast to object) , to see if we need to add a cast
105
+ var lambdaTemp = Expression . Lambda < Func < object , object ? > > ( EnsureObjectCompatibleResult ( current ) , parameterObj ) ;
106
106
var funcCurrent = lambdaTemp . Compile ( ) ;
107
107
// Evaluate this compiled function, to see if the result type is more specific than the current expression type. If so, cast to it
108
108
var result = funcCurrent ( dataItem ) ;
@@ -111,9 +111,15 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
111
111
current = Expression . Convert ( current , runtimeType ) ;
112
112
}
113
113
114
- return current ;
114
+ return EnsureObjectCompatibleResult ( current ) ;
115
115
}
116
116
117
+ static Expression EnsureObjectCompatibleResult ( Expression expression ) =>
118
+ typeof ( object ) . IsAssignableFrom ( expression . Type ) && ! expression . Type . IsValueType
119
+ ? expression
120
+ : Expression . Convert ( expression , typeof ( object ) ) ;
121
+
122
+
117
123
/// <summary>
118
124
/// Determines whether the specified object is numeric.
119
125
/// </summary>
0 commit comments