【发布时间】:2013-06-29 23:41:18
【问题描述】:
我正在尝试编写一个 ExpressionVisitor 来包装我的 LINQ-to-object 表达式,以自动使其字符串比较不区分大小写,就像它们在 LINQ-to-entities 中一样。
编辑:我绝对想使用 ExpressionVisitor 而不仅仅是在创建表达式时应用一些自定义扩展或其他东西,原因有一个:传递给我的 ExpressionVisitor 的表达式是由 ASP.Net Web API ODATA 生成的层,所以我无法控制它是如何生成的(即我不能小写它正在搜索的字符串,除非在这个 ExpressionVisitor 中)。
必须支持 LINQ to Entities。不仅仅是扩展。
这是我目前所拥有的。它在字符串上查找对“包含”的调用,然后对该表达式内的任何成员访问调用 ToLower。
但是,它不起作用。如果我在更改后查看表达式,它看起来对我来说是正确的,所以我不确定我可能做错了什么。
public class CaseInsensitiveExpressionVisitor : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (insideContains)
{
if (node.Type == typeof (String))
{
var methodInfo = typeof (String).GetMethod("ToLower", new Type[] {});
var expression = Expression.Call(node, methodInfo);
return expression;
}
}
return base.VisitMember(node);
}
private Boolean insideContains = false;
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == "Contains")
{
if (insideContains) throw new NotSupportedException();
insideContains = true;
var result = base.VisitMethodCall(node);
insideContains = false;
return result;
}
return base.VisitMethodCall(node);
}
如果我在 VisitMember 方法的“返回表达式”行设置断点,然后在“节点”和“表达式”变量上执行“ToString”,断点会被命中两次,这就是这两个设置的值是:
第一击:
node.ToString()
"$it.LastName"
expression.ToString()
"$it.LastName.ToLower()"
第二次命中:
node.ToString()
"value(System.Web.Http.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty"
expression.ToString()
"value(System.Web.Http.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty.ToLower()"
我对表达式的了解还不够,无法弄清楚我在这一点上做错了什么。有什么想法吗?
【问题讨论】:
-
string.Equals(string1, string2, StringComparison.InvariantCultureIgnoreCase)? -
避免使用
ToLower进行字符串比较,因为它更有可能导致错误 (Turkey Test)。要么使用大写,要么最好使用 Corak 建议的 String.Equals。 -
这在我的情况下不起作用。首先,我无法控制表达式,因为它是由 ASP.Net Web API 自动生成的。其次,我想要一些我可以用来包装 LINQ 语句的东西,并且可以与 LINQ-to-entities 和 LINQ-to-objects 一起使用。
-
@keyboardP:是的,我读到了土耳其测试。在这一点上,我对此并不担心。但是,一旦我开始工作,我会尝试使用大写字母。
-
@JoshMouch,相信你做得很好,你最终是否手动编写了整个 ODATA --> LINQ --> SQL,没有 ODATA V4 框架没有帮助? stackoverflow.com/q/47055350/1431250
标签: c# linq lambda expression-trees expressionvisitor