2009-04-08 9 views
50

は、私が検索してきたが、私は型にタイプ<機能<T, object>>

Expression<Func<T, DateTime>> 

からキャストする方法を見つけることができません。

Expression<Func<T, object>> 

私は広大な知識にもう一度回り込む必要があります)

答えて

62

同じ種類のものではないので、それらの間にキャストすることはできません。ただし、効果的に式ツリー内の変換を追加することができます。

ジョン(感謝ところで)あなたは完全な柔軟性のためにさらに一歩それを取ることができるからコードに基づいて
using System; 
using System.Linq.Expressions; 

class Test 
{ 
    // This is the method you want, I think 
    static Expression<Func<TInput,object>> AddBox<TInput, TOutput> 
     (Expression<Func<TInput, TOutput>> expression) 
    { 
     // Add the boxing operation, but get a weakly typed expression 
     Expression converted = Expression.Convert 
      (expression.Body, typeof(object)); 
     // Use Expression.Lambda to get back to strong typing 
     return Expression.Lambda<Func<TInput,object>> 
      (converted, expression.Parameters); 
    } 

    // Just a simple demo 
    static void Main() 
    { 
     Expression<Func<string, DateTime>> x = text => DateTime.Now; 
     var y = AddBox(x);   
     object dt = y.Compile()("hi"); 
     Console.WriteLine(dt); 
    }   
} 
+0

@JonSkeet Expression.Convertは常に良い考えではありません。私の答えを見てください。 – Rookian

8

public static Expression<Func<TModel, TToProperty>> Cast<TModel, TFromProperty, TToProperty>(Expression<Func<TModel, TFromProperty>> expression) 
{ 
    Expression converted = Expression.Convert(expression.Body, typeof(TToProperty)); 

    return Expression.Lambda<Func<TModel, TToProperty>>(converted, expression.Parameters); 
} 
+0

この使用例はありますか? –

23

答えをRobおよびJon Skeetに1つの問題があります。

あなたはx => Convert(x.PropertyName)ような何かを得るが、多くの場合、ASP.NET MVCのインスタンスのためにあなたは、このx => x.PropertyName

のような表現がそうExpression.Convertいくつかのケースのための「汚染」表現で欲しいです。

ソリューション:

public static class LambdaExpressionExtensions 
{ 
    public static Expression<Func<TInput, object>> ToUntypedPropertyExpression<TInput, TOutput> (this Expression<Func<TInput, TOutput>> expression) 
    { 
     var memberName = ((MemberExpression)expression.Body).Member.Name; 

     var param = Expression.Parameter(typeof(TInput)); 
     var field = Expression.Property(param, memberName); 
     return Expression.Lambda<Func<TInput, object>>(field, param); 
    } 
} 

用途:

Expression<Func<T, DateTime>> expression = ...; 
Expression<Func<T, object>> expr = expression.ToUntypedPropertyExpression(); 
+7

これはうまくいかないようです。例えば、私は 'Int32'を' object'に変換することはできないようです。それは 'Convert'呼び出しのためのものです。それがなければ、私は 'ArgumentException'を取得します。 'DateTime'バージョンを試してみましょう。これはあなたのために働いた場合、私はあなたが参照型でそれをしたと推測しています。 –

0

ただ、それはすべてのデータタイプのために働く、オブジェクトとしてアウトTResultを定義し、表現をコンパイル。

Expression<Func<string, object>> dateExp = text => DateTime.Now; 
object dt = dateExp.Compile()("hi"); 
Console.WriteLine(dt); 

Fiddle sample here