Skip to content

Commit fc10df0

Browse files
committed
Fix for integer result; explicit cast to object was missing for value type results of the property path
Signed-off-by: Daniël Trommel <[email protected]>
1 parent 67306e0 commit fc10df0

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

src/Extensions/ObjectExtensions.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ internal static partial class ObjectExtensions
2828
try
2929
{
3030
// 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);
3333

3434
// 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);
3636
var _compiledPropertyPath = lambda.Compile();
3737
return _compiledPropertyPath;
3838
}
@@ -50,7 +50,7 @@ internal static partial class ObjectExtensions
5050
/// <param name="bindingPath">The binding path to access.</param>
5151
/// <param name="dataItem">The actual data item to use for runtime type evaluation, to help with any needed subclass type conversions.</param>
5252
/// <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)
5454
{
5555
Expression current = parameterObj;
5656

@@ -80,15 +80,15 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
8080
else
8181
{
8282
// 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)])
8484
?? throw new ArgumentException($"Type '{current.Type.Name}' does not support integer indexing");
8585
current = Expression.Property(current, indexerProperty, Expression.Constant(index));
8686
}
8787
}
8888
else
8989
{
9090
// 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)])
9292
?? throw new ArgumentException($"Type '{current.Type.Name}' does not support string indexing");
9393
current = Expression.Property(current, indexerProperty, Expression.Constant(stringIndex));
9494
}
@@ -101,8 +101,8 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
101101
current = Expression.Property(current, propertyInfo);
102102
}
103103

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);
106106
var funcCurrent = lambdaTemp.Compile();
107107
// Evaluate this compiled function, to see if the result type is more specific than the current expression type. If so, cast to it
108108
var result = funcCurrent(dataItem);
@@ -111,9 +111,15 @@ private static Expression BuildPropertyPathExpression(ParameterExpression parame
111111
current = Expression.Convert(current, runtimeType);
112112
}
113113

114-
return current;
114+
return EnsureObjectCompatibleResult(current);
115115
}
116116

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+
117123
/// <summary>
118124
/// Determines whether the specified object is numeric.
119125
/// </summary>

0 commit comments

Comments
 (0)