Speed up expression delegates when widening types is not needed
This commit is contained in:
@@ -105,18 +105,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
|
||||
|
||||
Expression argExpression;
|
||||
|
||||
if (parameterType.IsValueType())
|
||||
{
|
||||
BinaryExpression ensureValueTypeNotNull = Expression.Coalesce(paramAccessorExpression, Expression.New(parameterType));
|
||||
|
||||
argExpression = EnsureCastExpression(ensureValueTypeNotNull, parameterType);
|
||||
}
|
||||
else
|
||||
{
|
||||
argExpression = EnsureCastExpression(paramAccessorExpression, parameterType);
|
||||
}
|
||||
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
|
||||
|
||||
if (isByRef)
|
||||
{
|
||||
@@ -349,26 +338,39 @@ namespace Newtonsoft.Json.Utilities
|
||||
Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
private Expression EnsureCastExpression(Expression expression, Type targetType)
|
||||
|
||||
private Expression EnsureCastExpression(Expression expression, Type targetType, bool allowWidening = false)
|
||||
{
|
||||
Type expressionType = expression.Type;
|
||||
|
||||
|
||||
// check if a cast or conversion is required
|
||||
if (expressionType == targetType || (!expressionType.IsValueType() && targetType.IsAssignableFrom(expressionType)))
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
if (targetType.IsPrimitive())
|
||||
if (targetType.IsValueType())
|
||||
{
|
||||
MethodInfo toTargetTypeMethod = typeof(Convert)
|
||||
.GetMethod("To" + targetType.Name, new[] { typeof(object) });
|
||||
Expression convert = Expression.Unbox(expression, targetType);
|
||||
|
||||
if (toTargetTypeMethod != null)
|
||||
if (allowWidening && targetType.IsPrimitive())
|
||||
{
|
||||
expression = Expression.Call(toTargetTypeMethod, expression);
|
||||
MethodInfo toTargetTypeMethod = typeof(Convert)
|
||||
.GetMethod("To" + targetType.Name, new[] { typeof(object) });
|
||||
|
||||
if (toTargetTypeMethod != null)
|
||||
{
|
||||
convert = Expression.Condition(
|
||||
Expression.TypeIs(expression, targetType),
|
||||
convert,
|
||||
Expression.Call(toTargetTypeMethod, expression));
|
||||
}
|
||||
}
|
||||
|
||||
return Expression.Condition(
|
||||
Expression.Equal(expression, Expression.Constant(null, typeof(object))),
|
||||
Expression.Default(targetType),
|
||||
convert);
|
||||
}
|
||||
|
||||
return Expression.Convert(expression, targetType);
|
||||
|
||||
Reference in New Issue
Block a user