Why the following code throws an exception at runtime开发者_运维技巧, whereas doing it in the traditional way compiles without problem?
var left = Expression.Constant(25d);
var right = Expression.Constant(20);
// Throws an InvalidOperationException!
var multiplyExpression = Expression.Multiply(left, right);
var multiply = 25d * 20;
Debug.WriteLine(multiply.ToString()); // Works normally!
I won't use Expression.Convert
since I can't determine exactly which expression should be converted.
var left = Expression.Constant(25d);
var right = Expression.Constant(20);
var multiplyExpression = Expression.Multiply(
left,
Expression.Convert(right, left.Type));
Or, if you don't know that the left side has higher precision, and you want to always end up with a double
result, you could say something like:
Expression left = Expression.Constant(2);
Expression right = Expression.Constant(25.1);
left = Expression.Convert(left, typeof(double));
right = Expression.Convert(right, typeof(double));
var multiplyExpression = Expression.Multiply(left, right);
Well, I figured out how to solve the problem using TypeCode enumeration to determine which node would have higher type precision, then convert the latter node's type to the former's type, and vice versa:
private static void Visit(ref Expression left, ref Expression right)
{
var leftTypeCode = Type.GetTypeCode(left.Type);
var rightTypeCode = Type.GetTypeCode(right.Type);
if (leftTypeCode == rightTypeCode)
return;
if (leftTypeCode > rightTypeCode)
right = Expression.Convert(right, left.Type);
else
left = Expression.Convert(left, right.Type);
}
Well the error message in your title is telling you why there is an exception.
There is no Expression.Multiply
method defined which takes a System.Int32
and a System.Double
as arguments.
The *
will work because it's lower level and your values will be type cast automatically.
var left = Expression.Constant(25d);
var right = Expression.Constant((double)20);
var multiplyExpression = Expression.Multiply(left, right); // works
精彩评论