Tôi đang cố gắng viết ExpressionVisitor để bao quanh các biểu thức LINQ-to-object để tự động so sánh chuỗi trường hợp không nhạy cảm, giống như chúng nằm trong LINQ-to-entity.Chuỗi phân biệt chữ hoa chữ thường so sánh trong biểu thức LINQ
CHỈNH SỬA: Tôi chắc chắn muốn sử dụng ExpressionVisitor thay vì chỉ áp dụng một số tiện ích mở rộng tùy chỉnh hoặc thứ gì đó cho biểu thức của tôi khi được tạo ra vì một lý do quan trọng: Biểu thức được chuyển tới ExpressionVisitor của tôi được tạo bởi API Web ASP.Net Lớp ODATA, vì vậy tôi không có quyền kiểm soát cách nó được tạo ra (nghĩa là tôi không thể viết thường chuỗi mà nó đang tìm kiếm ngoại trừ từ bên trong ExpressionVisitor này).
Có hỗ trợ LINQ cho thực thể. Không chỉ mở rộng.
Đây là những gì tôi có cho đến nay. Nó tìm kiếm một cuộc gọi đến "Chứa" trên một chuỗi và sau đó gọi ToLower trên bất kỳ quyền truy cập thành viên nào bên trong biểu thức đó.
Tuy nhiên, nó không hoạt động. Nếu tôi xem các biểu thức sau khi thay đổi của tôi, nó có vẻ đúng với tôi, vì vậy tôi không chắc chắn những gì tôi có thể làm sai.
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);
}
Nếu tôi đặt một breakpoint trên dòng "trở lại khái niệm" trong phương pháp VisitMember và sau đó làm một "ToString" trên "nút" và "khái niệm" các biến, các điểm break được nhấn hai lần, và đây là những gì hai bộ giá trị là:
Đầu tiên hit:
node.ToString()
"$it.LastName"
expression.ToString()
"$it.LastName.ToLower()"
thứ hai hit:
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()"
Tôi không biết đủ về các biểu thức để tìm ra những gì tôi đang làm sai tại thời điểm này. Bất kỳ ý tưởng?
'string.Equals (string1, string2, StringComparison.InvariantCultureIgnoreCase)'? – Corak
Tránh 'ToLower' để so sánh chuỗi vì có nhiều khả năng dẫn đến lỗi ([Turkey Test] (http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html)). Hoặc sử dụng chữ hoa hoặc tốt hơn, như Corak đề nghị, String.Equals. – keyboardP
Điều này sẽ không hoạt động trong trường hợp của tôi. Đầu tiên, tôi không có quyền kiểm soát Biểu thức, vì nó được tự động tạo bởi API Web ASP.Net. Thứ hai, tôi muốn một cái gì đó mà tôi có thể sử dụng chung để bọc một câu lệnh LINQ và sẽ làm việc với cả LINQ-to-entity lẫn LINQ-to-objects. –