[英]Expression to convert numeric values: System.InvalidCastException: > Unable to cast object of type 'System.Int32' to type 'System.Int64'
I'm trying to create an expression to convert some numeric values.我正在尝试创建一个表达式来转换一些数值。 Here is what I have tried:这是我尝试过的:
public object ConvertValue(object value, Type targetType) {
var parameter = Expression.Parameter(typeof(object), "p"); // "p"
var convert = Expression.Convert(parameter, targetType); // Convert(p, Int64)
var targetConvert = Expression.Convert(convert, typeof(object)); // Convert(Convert(p, Int64), Object)
var lambda = Expression.Lambda<Func<object,object>>(targetConvert, parameter); // p => Convert(Convert(p, Int64), Object)
var method = lambda.Compile();
var result = method(value); // HERE I GET THE ERROR!
return result;
}
But when I call it, as this simple test:但是当我调用它时,就像这个简单的测试:
[Fact]
public void TestConvert() {
var result = ConvertValue(23, typeof(long));
Assert.Equal(typeof(long), result.GetType());
}
I get the error:我得到错误:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. System.Reflection.TargetInvocationException:调用的目标已引发异常。 ---> System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Int64'. ---> System.InvalidCastException:无法将“System.Int32”类型的 object 转换为“System.Int64”类型。
at lambda_method(Closure, Object ) bla bla bla...在 lambda_method(关闭,Object)bla bla bla ...
Any idea what's happening here and what Int32
cannot be cast to Int64
?知道这里发生了什么以及Int32
不能转换为Int64
吗? Thanks in advance.提前致谢。
The following takes advantage of Convert.ChangeType
to provide more flexibility with the conversions.下面利用Convert.ChangeType
为转换提供更大的灵活性。
The code comments document what is being done.代码注释记录了正在做什么。
public object ConvertValue(object value, Type targetType){
var valueType = value.GetType();
// Func<TValue,TTarget>
var delegateType = typeof(Func<,>).MakeGenericType(valueType, targetType);
var convert = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) });
// TValue p
var parameter = Expression.Parameter(valueType, "p");
// Convert.ChangeType(Convert(p), targetType);
var changeType = Expression.Call(convert, Expression.Convert(parameter, typeof(object)), Expression.Constant(targetType));
// (TTarget)Convert.ChangeType(Convert(p), targetType);
var body = Expression.Convert(changeType, targetType);
//Func<TValue,TTarget> = TValue p => (TTarget)Convert.ChangeType(Convert(p), targetType);
var lambda = Expression.Lambda(delegateType, body, parameter);
var method = lambda.Compile();
var result = method.DynamicInvoke(value);
return result;
}
The following basic tests all passed when exercised以下基本测试在运动时全部通过
[TestMethod]
public void Should_Convert_Int_To_Long() {
var expected = typeof(long);
var actual = ConvertValue(23, expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_Long_To_Int() {
var expected = typeof(int);
var actual = ConvertValue((long)23, expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_String_To_Long() {
var expected = typeof(long);
var actual = ConvertValue("23", expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_String_To_Int() {
var expected = typeof(int);
var actual = ConvertValue("23", expected);
Assert.AreEqual(expected, actual.GetType());
}
What you try to do is (int64)(object)23
and it won't work because 23
is of type int32
.您尝试做的是(int64)(object)23
,它不起作用,因为23
是int32
。 You can pass 23L
literal and it'll work:您可以通过23L
文字,它会工作:
ConvertValue(23L, typeof(long));
To make your code work, you need to call convert from int32
to int64
after unboxing:为了使您的代码正常工作,您需要在拆箱后调用 convert from int32
to int64
:
public static object ConvertValue(object value, Type targetType) {
var parameter = Expression.Parameter(typeof(object), "p"); // "p"
var convert = Expression.Convert(Expression.Convert(parameter, value.GetType()), targetType); // Convert(p, Int64)
var targetConvert = Expression.Convert(convert, typeof(object)); // Convert(Convert(p, Int64), Object)
var lambda = Expression.Lambda<Func<object,object>>(targetConvert, parameter); // p => Convert(Convert(p, Int64), Object)
var method = lambda.Compile();
var result = method(value);
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.