2009-04-08 8 views
50

내가 찾고 있었어요하지만 난 종류에 유형<Func을 <T, object>>

Expression<Func<T, DateTime>> 

에서 주조하는 방법을 찾을 수 없습니다 :

Expression<Func<T, object>> 

그래서 나는 다시 엄청난 지식으로 돌아 가야 만한다.)

답변

62

그들은 같은 종류가 아니기 때문에 그들 사이에서 단지 캐스트 할 수 없다. 그러나, 당신은 효과적으로 식 트리 내에서 변환을 추가 할 수 있습니다 : 존에서 코드 (BTW 감사)을 바탕으로

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

답변을 RobJon Skeet에는 한 가지 문제가 있습니다.

당신은 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