2012-05-01 12 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 S,GetFactors將返回一個IEnumerable<object>含有ab

實施例2

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

GetFactors將返回含有obj1obj2abc,和一個dIEnumerable<object>

+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

相關問題