2013-06-10 3 views
2

표현식 트리의 수정에 어려움을 겪고 있습니다. 예제를 단순화하여 여기에 표시하기 쉽도록했습니다.표현식 트리에서 유형 바꾸기

public class Filter 
    { 
     public string FilterableProperty1 { get; set; } 
     public string FilterableProperty2 { get; set; } 
    } 

    public class Entity 
    { 
     public string FilterableProperty1 { get; set; } 
     public string FilterableProperty2 { get; set; } 
     public string NonFilterableProperty { get; set; } 
    } 

필터 클래스의 모든 속성도 Entity 클래스에 있습니다. 지금은 이런 방법으로 원하는 개체를 반환하는 필터 클래스를 사용하고 싶습니다 :

public IEnumerable<Entity> GetEntities(Expression<Func<Filter, bool>> filter) 
    { 
     Expression<Func<Entity, bool>> convertedFilter = Expression.Lambda<Func<Entity, bool>>(
      filter.Body, 
      Expression.Parameter(typeof(Entity), filter.Parameters[0].Name)); 

     using (MyEntities entities = new MyEntities()) 
     { 
      return entities.Entities.Where(convertedFilter); 
     } 
    } 

을 그래서 기본적으로 난 그냥 expression 매개 변수의 유형을 변경합니다. 이제 다음과 같은 함수를 호출하면 :

public IEnumerable<Entity> GetFilteredEntities() 
    { 
     return GetEntities(x => x.FilterableProperty1 == "Test"); 
    } 

예외가 발생합니다. 매개 변수 x가 지정된 쿼리 식에서 발견되지 않았습니다. 분명히 ParameterExpression을 대체하여 무언가를 깨고 있습니다. 원래 표현식의 본문을 대신하는 (또는 다시 작성하는) 올바른 유형의 새 표현식을 만들려면 어떻게해야합니까?

답변

4

좀 더 검색 한 후에 나는 대답을 찾았습니다 : How to change a type in an expression tree?. 질문을 제출했을 때 제안에 표시되지 않았습니다.

필터 클래스가 실제로 필요하지 않기 때문에 대신 (IEntity)를 필터링 할 수있는 속성 만 가진 인터페이스를 만들고 인터페이스를 구현하기 위해 Entity 클래스를 수정했습니다. 이제 내가 원하는이와 결과를 얻을 수 있어요 : 비슷한 일을해야 할 경우에

// Example use: return entities.Entities.Where(ExpressionTransformer<IEntity,Entity>.Transform(filter)); 
internal static class ExpressionTransformer<TFrom, TTo> where TTo : TFrom 
{ 
    public class Visitor : ExpressionVisitor 
    { 
     private ParameterExpression _parameter; 

     public Visitor(ParameterExpression parameter) 
     { 
      _parameter = parameter; 
     } 

     protected override Expression VisitParameter(ParameterExpression node) 
     { 
      return _parameter; 
     } 
    } 

    public static Expression<Func<TTo, bool>> Tranform(Expression<Func<TFrom, bool>> expression) 
    { 
     ParameterExpression parameter = Expression.Parameter(typeof(TTo)); 
     Expression body = new Visitor(parameter).Visit(expression.Body); 
     return Expression.Lambda<Func<TTo, bool>>(body, parameter); 
    } 
} 

을하지만 인터페이스와 함께 작동하지 않을 수 있습니다 또는 당신이 당신의 클래스가 인터페이스를 구현 할 수 없습니다 : 대답은에도 위에서 말한 대답

+0

톰 감사합니다. 내 하루를 구하십시오! –

관련 문제