我试图转换参数表达式并且无法转换为值类型。以下是我的代码示例:
public static MemberExpression ConvertToType(ParameterExpression sourceParameter,
PropertyInfo propertyInfo,
TypeCode typeCode)
{
var sourceExpressionProperty = Expression.Property(sourceParameter, sourceProperty);
//throws an exception if typeCode is a value type.
Expression convertedSource = Expression.Convert(sourceExpressionProperty,
Type.GetType("System." + typeCode));
return convertedSource;
}
我收到以下无效操作异常:
No coercion operator is defined between types 'System.String' and 'System.Decimal'.
非常感谢任何有关此转换的帮助。
答案 0 :(得分:4)
public class ExpressionUtils
{
public static MethodCallExpression ConvertToType(
ParameterExpression sourceParameter,
PropertyInfo sourceProperty,
TypeCode typeCode)
{
var sourceExpressionProperty = Expression.Property(sourceParameter, sourceProperty);
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var callExpressionReturningObject = Expression.Call(changeTypeMethod, sourceExpressionProperty, Expression.Constant(typeCode));
return callExpressionReturningObject;
}
}
请注意,生成的表达式是对Convert.ChangeType方法的调用,该方法将返回System.Object。
这是一个单元测试:
[TestClass]
public class UnitTest1
{
private class MyClass
{
public string ValueAsString { get; set; }
}
[TestMethod]
public void TestMethod1()
{
var parameter = Expression.Parameter(typeof(MyClass));
var property = typeof(MyClass).GetProperty("ValueAsString");
var lambdaBody = ExpressionUtils.ConvertToType(parameter, property, TypeCode.Decimal);
var lambda = Expression.Lambda<Func<MyClass, object>>(lambdaBody, parameter);
var valueAsDecimal = (decimal) lambda.Compile().Invoke(new MyClass { ValueAsString = "42" });
Assert.AreEqual(42m, valueAsDecimal);
}
}
答案 1 :(得分:1)
我选择的解决方案是:
private static Expression GetConvertedSource(ParameterExpression sourceParameter,
PropertyInfo sourceProperty,
TypeCode typeCode)
{
var sourceExpressionProperty = Expression.Property(sourceParameter,
sourceProperty);
var changeTypeCall = Expression.Call(typeof(Convert).GetMethod("ChangeType",
new[] { typeof(object),
typeof(TypeCode) }),
sourceExpressionProperty,
Expression.Constant(typeCode)
);
Expression convert = Expression.Convert(changeTypeCall,
Type.GetType("System." + typeCode));
var convertExpr = Expression.Condition(Expression.Equal(sourceExpressionProperty,
Expression.Constant(null, sourceProperty.PropertyType)),
Expression.Default(Type.GetType("System." + typeCode)),
convert);
return convertExpr;
}
请注意Expression.Condition
处理空值。