2015-08-15 65 views
3

我有一个int字段的ExpandoObject,我想用表达式树将它转换为小数。如何使用表达式树对数值类型应用隐式转换?

这里是我使用的方法:

private static Expression<Func<dynamic, decimal>> CreateLambdaCastExpression() 
    { 
     // source 
     var sourceParameterExpression = Expression.Parameter(typeof (object), "source"); 

     var binder = Binder.GetMember(
      CSharpBinderFlags.None, "IntProp", typeof (ExpressionTreeUtils), 
      new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}); 
     // source.sourceProperty 
     var sourcePropertyExpression = Expression.Dynamic(
      binder, typeof (object), sourceParameterExpression); 

     // (decimal) source; 
     var castedValueExpression = Expression.Convert(sourcePropertyExpression, typeof (decimal)); 

     //() => (decimal) source; 
     return Expression.Lambda<Func<dynamic, decimal>>(castedValueExpression, 
      sourceParameterExpression); 
    } 

调用它这样会导致一个InvalidCastException:

 dynamic source = new ExpandoObject(); 
     source.IntProp = 1; 

     decimal r = CreateLambdaCastExpression().Compile()(source); 

如果我设置source.IntProp 1米,它的工作原理(显然)

我读过msdn ExpressionConvert只对用户定义的类型执行隐式转换,所以这可能是解释。

有关如何对数值类型执行隐式转换的任何想法?

+0

不知道我完全得到了这个。但我相信'Expression.Convert'遵循“实现方法是'null'”,因为“'expression.Type'是一个引用类型”。它是'物体'。所以可能如果它是'var sourcePropertyExpression = Expression.Dynamic( 活页夹,typeof(int),sourceParameterExpression);'这会有所帮助。 – Artyom

回答

3

更改这些行:

// CSharpBinderFlags.ConvertExplicit: explicit cast 
// (will convert double to decimal) 
// CSharpBinderFlags.None: implicit cast 
// (will convert int to decimal, won't convert double to decimal) 
var convert = Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(decimal), typeof(ExpressionTreeUtils)); 

// (decimal) source; 
var castedValueExpression = Expression.Dynamic(
    convert, typeof(decimal), sourcePropertyExpression); 

注意有关隐式/显式类型转换的注释。

(所以唯一改变的是var castedValueExpression是如何构建的)

ideone以饱满的例子。

+0

的确,这就是我错过的!谢谢 :) – Brann