2015-08-15 3 views
3

У меня есть объект ExpandoObject с полем int, и я хочу передать его в десятичное число, используя дерево выражений.Как применить неявное приведение к числовым типам с использованием деревьев выражений?

Вот метод я использую:

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 »как« выражение ». Тип» является ссылочным типом ». Это «объект». Так что, вероятно, если это 'var sourcePropertyExpression = Expression.Dynamic ( binder, 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