2015-12-23 57 views
1

比方说,我有这样的表达:递归检查LINQ表达式

e => e.Name.StartsWith(GetArgument()) 

GetArgument()定义如下:

public string GetArgument() { return "Lu"; } 

我想这个表达式被翻译成以下字符串:

"begins_with(Name, Lu)" 

我开发了一个表达式访问器来访问rec中的每个子表达式ursive方式:

public class MyExpressionTranslator : ExpressionVisitor, IExpressionTranslator<string> 
{ 
    // .... 

    //Implementing IExpressionTranslator<string> 
    public string Translate(Expression expr) 
    { 
      //Begin visiting the expression and its sub expressions 
      base.Visit(expr); 

      // I need to return the string here 
      return null; 
    } 

    // Overrides method from base class ExpressionVisitor 
    protected override MethodCallExpression VisitMethodCall(MethodCallExpression expr) 
    { 
     //This method is called when a method call sub expression is visited 

     //For example, I can check if the method being called is "StartsWith" 
     if(expr.Method.Name == "StartsWith") 
     { 
      // I have no idea what to do here 
     } 

     //Proceeds to visit this expression's sub expressions 
     return base.VisitMethodCall(expr); 
    } 
} 

如下我会用这个类:

MyExpressionTranslator translator = // new MyExpressionTranslator(...) 
Expression<Func<SomeClass, bool>> expr = e => e.Name.StartsWith(GetArgument()); 
string result = translator.Translate(expr); 
// result should be "begins_with(Name, Lu)" 

提供了我的基类具有用于每个表达式类型一个virtual访问方法(可能是一个常数,一个参数,一个方法调用,或任何其他)我该如何构建预期的字符串输出?

+0

您正在为特定情况提供预期输出。其他情况下,例如属性访问或循环可能如何? –

+0

@YacoubMassad其实,我打算将这个特定的案例解决方案扩展到任何其他用例。这里的核心问题是我不知道如何递归地创建字符串。一旦解决了,我可以设法做其他事情。 –

+1

提示:使用私有字段StringBuilder。 –

回答

0

你想完成什么?像下面的东西可能会起作用。尽管填写其他方法并不容易。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Expression<Func<TestObject, bool>> expr = e => e.FirstName.StartsWith(GetArgument()); 
     var visitor = new MyExpressionTranslator(); 
     var translation = visitor.Translate(expr); // = "begins_with(FirstName, Lu)" 
    } 

    static string GetArgument() 
    { 
     return "Lu"; 
    } 
} 

class TestObject 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public interface IExpressionTranslator<T> 
{ 
    T Translate(Expression expr); 
} 

public class MyExpressionTranslator : ExpressionVisitor, IExpressionTranslator<string> 
{ 
    private StringBuilder _sb = null; 
    public string Translate(Expression expr) 
    { 
     _sb = new StringBuilder(); 
     base.Visit(expr); 

     // I need to return the string here 
     return _sb.ToString(); 
    } 

    protected override Expression VisitMethodCall(MethodCallExpression expr) 
    { 
     if (expr.Method.Name == "StartsWith") 
     { 
      var mainArg = expr.Arguments[0]; 
      var lambda = Expression.Lambda<Func<string>>(mainArg); 
      var arg = lambda.Compile()(); 

      var member = expr.Object as MemberExpression; 
      if (member != null) 
      { 
       _sb.AppendFormat("begins_with({0}, {1})", member.Member.Name, arg); 
      } 
      else 
      { 
       //Don't know what you want here. 
       _sb.AppendFormat("begins_with({0}, {1}))", "(obj)", arg); 
      } 
     } 
     return base.VisitMethodCall(expr); 
    } 
}