2015-08-15 62 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