所以,我确实调查了访问者模式,但我无法让它以我喜欢的方式工作,所以我有点破解了一个解决方案。:/
我已经使用基本示例创建了一个基本 QueryContext 来解析树并构建字符串集合。我最终得到的是这样的东西。它绝不是完整的,但它是一个不错的开始:
public object Execute(Expression expression, bool IsEnumerable)
{
// Find the call to Where() and get the lambda expression predicate.
InnermostWhereFinder whereFinder = new InnermostWhereFinder();
MethodCallExpression whereExpression = whereFinder.GetInnermostWhere(expression);
LambdaExpression lambdaExpression = (LambdaExpression)((UnaryExpression)(whereExpression.Arguments[1])).Operand;
// Send the lambda expression through the partial evaluator.
lambdaExpression = (LambdaExpression)Evaluator.PartialEval(lambdaExpression);
// Assemble the strings necessary to build this.
var strings = new List<string>();
GetStrings(lambdaExpression.Body, strings);
var query = String.Join(" ", strings);
return ExecuteQuery(query);
}
public abstract object ExecuteQuery(string whereClause);
public abstract Dictionary<ExpressionType, string> ExpressionTypeToStringMap { get; }
public abstract string FormatFieldName(string fieldName);
public abstract string FormatConstant(string constant);
void GetStrings(System.Linq.Expressions.Expression expression, List<string> toReturn)
{
if (expression is BinaryExpression)
{
// Binary expression. Recurse and add to the list.
GetStrings((BinaryExpression)(expression), toReturn);
}
else if (expression is MemberExpression)
{
var e = (MemberExpression)(expression);
toReturn.Add(FormatFieldName(e.Member.Name));
}
else if (expression is ConstantExpression)
{
var e = (ConstantExpression)(expression);
toReturn.Add(FormatConstant((string)(e.Value)));
}
else
{
throw new NotImplementedException("Unaware of how to handle type " + expression.GetType().ToString());
}
}
string NodeTypeToString(ExpressionType type)
{
var map = ExpressionTypeToStringMap;
if(map.ContainsKey(type))
{
return map[type];
}
throw new NotImplementedException("Type '" + type.ToString() + "' not implemented in ExpressionTypeToStringMap.");
}
void GetStrings(BinaryExpression expression, List<string> toReturn)
{
toReturn.Add("(");
if (expression.Left != null)
GetStrings(expression.Left, toReturn);
toReturn.Add(NodeTypeToString(expression.NodeType));
if (expression.Right != null)
GetStrings(expression.Right, toReturn);
toReturn.Add(")");
}
欢迎更好的实现,但至少现在我没有被阻止。