Ich versuche einen ExpressionVisitor zu schreiben, der meine LINQ-zu-Objekt-Ausdrücke umschließt, damit ihre Zeichenfolgenvergleiche unabhängig von der Groß-/Kleinschreibung in LINQ-to-entities erfolgen.Groß-/Kleinschreibung in LINQ-Ausdruck vergleichen
EDIT: Ich möchte definitiv eine ExpressionVisitor statt nur einige benutzerdefinierte Erweiterung oder etwas auf meinen Ausdruck anwenden, wenn es aus einem wichtigen Grund erstellt: Der Ausdruck an meine ExpressionVisitor wird von der ASP.Net Web API generiert ODATA-Ebene, also habe ich keine Kontrolle darüber, wie sie erzeugt wird (dh ich kann die gesuchte Zeichenkette nur in diesem ExpressionVisitor nicht klein schreiben).
Muss LINQ zu Entities unterstützen. Nicht nur Erweiterung.
Hier ist, was ich bisher habe. Es sucht nach einem Aufruf von "Contains" in einer Zeichenfolge und ruft dann ToLower für jeden Mitgliedszugriff innerhalb dieses Ausdrucks auf.
Allerdings funktioniert es nicht. Wenn ich die Ausdrücke nach meinen Änderungen ansehe, sieht das für mich richtig aus, also bin ich mir nicht sicher, was ich falsch machen könnte.
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);
}
Wenn ich einen Haltepunkt auf der „Rückkehr Ausdruck“ Zeile in der VisitMember Methode festgelegt und dann ein „ToString“ auf dem „Knoten“ und „Ausdruck“ Variablen, wird der Haltepunkt zweimal getroffen, und hier ist was die beiden Sätze von Werten sind:
Erster Treffer:
node.ToString()
"$it.LastName"
expression.ToString()
"$it.LastName.ToLower()"
Zweiter Treffer:
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()"
Ich weiß nicht genug über Ausdrücke, um herauszufinden, was ich an diesem Punkt falsch mache. Irgendwelche Ideen?
'string.Equals (string1, string2, StringComparison.InvariantCultureIgnoreCase)'? – Corak
Vermeiden Sie 'ToLower' für den Zeichenfolgenvergleich, da es mit höherer Wahrscheinlichkeit zu einem Fehler kommt ([Puten Test] (http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html))). Verwenden Sie entweder Großbuchstaben oder vorzugsweise, wie Corak vorgeschlagen hat, String.Equals. – keyboardP
Dies funktioniert in meinem Fall nicht. Erstens habe ich keine Kontrolle über den Ausdruck, da er automatisch von der ASP.Net-Web-API generiert wird. Zweitens möchte ich etwas, das ich generisch verwenden kann, um eine LINQ-Anweisung zu umbrechen und wird sowohl mit LINQ-to-Entities als auch mit LINQ-to-Objects arbeiten. –