2012-05-01 1 views
3

임의의 표현식이 Expression<Func<int>> 인 경우 결과에 영향을 줄 수 있지만 반드시 그런 것은 아니지만 모든 개체 목록을 어떻게 얻을 수 있습니까?출력에 영향을 미치는 표현식 트리의 모든 요소를 ​​얻는 방법

이 같은 기능을 찾고 있어요 :

IEnumerable<object> GetFactors(Expression<Func<int>> expression) 
{ 
    //return a list of all objects in the expression that affect the result. 
} 

예 1

Expression<Func<int>> expression =() => a + b; 

abint의, GetFactorsab을 포함하는 IEnumerable<object>을 반환합니다.

예 2

Expression<Func<int>> expression =() => obj1 != obj2 ? a + b : c + d; 

GetFactorsIEnumerable<object>obj1, obj2, a, b, cd 함유 반환.

+0

기본적으로 모든 끝점 (잎) 또는 죽은 코드를 감지하고 싶습니까? –

+0

@HenkHolterman : 죽은 코드는 신경 쓰지 않습니다. 나는 모든 나뭇잎, 죽은 코드를 찾고 있습니다. 트리에있는 모든 표현식의 모든 피연산자에 관심이 있다고 말하는 것이 맞을 것이라고 생각합니다. – Verax

답변

2

당신은 다음과 같이 정의 발현 방문자를 구현해야합니다

public class FactorVisitor : ExpressionVisitor 
{ 
    List<object> factors = new List<object>(); 

    private FactorVisitor(Expression<Func<int>> expression) 
    { 
     Visit(expression); 
    } 

    public static List<object> GetFactors(Expression<Func<int>> expression) 
    { 
     return new FactorVisitor(expression).factors; 
    } 

    // Add this method for listing compile-time constant values 
    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     factors.Add(node.Value); 
     return node; 
    } 

    protected override Expression VisitMember(MemberExpression node) 
    { 
     if (CanBeEvaluated(node)) 
     { 
      factors.Add(Evaluate(node)); 
     } 
     return node; 
    } 

    private static bool CanBeEvaluated(MemberExpression exp) 
    { 
     while (exp.Expression.NodeType == ExpressionType.MemberAccess) 
     { 
      exp = (MemberExpression) exp.Expression; 
     } 

     return (exp.Expression.NodeType == ExpressionType.Constant); 
    } 

    private static object Evaluate(Expression exp) 
    { 
     if (exp.NodeType == ExpressionType.Constant) 
     { 
      return ((ConstantExpression) exp).Value; 
     } 
     else 
     { 
      MemberExpression mexp = (MemberExpression) exp; 
      object value = Evaluate(mexp.Expression); 

      FieldInfo field = mexp.Member as FieldInfo; 
      if (field != null) 
      { 
       return field.GetValue(value); 
      } 
      else 
      { 
       PropertyInfo property = (PropertyInfo) mexp.Member; 
       return property.GetValue(value, null); 
      } 
     } 
    } 
} 

당신은 심지어 a.b 형상 부재 호출, 변수의 값을 얻을 것이다 있습니다.