假设我有这样的表达方式:
e => e.Name.StartsWith(GetArgument())
GetArgument()
的定义如下:
public string GetArgument() { return "Lu"; }
我希望将此表达式转换为以下字符串:
"begins_with(Name, Lu)"
我开发了一个表达式访问者,以递归方式访问每个子表达式:
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)
你想要完成什么?像下面这样的东西可能会起作用。尽管如此,填写其他方法并不容易。
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);
}
}