Ausdrucksbaum für die Methode String.IndexOf

c# expression-trees linq-expressions reflection

Frage

Wie soll ich Ausdrucksbaum für string.IndexOf("substring", StringComparison.OrdinalIgnoreCase) ?

Ich kann es ohne das zweite Argument arbeiten: StringComparison.OrdinalIgnoreCase . Das sind meine bisherigen Versuche:

var methodCall = typeof (string).GetMethod("IndexOf", new[] {typeof (string)});
Expression[] parms = new Expression[]{right, Expression.Constant("StringComparison.OrdinalIgnoreCase", typeof (Enum))};
var exp =  Expression.Call(left, methodCall, parms);
return exp;

Habe es auch versucht:

var methodCall = typeof (string).GetMethod(method, new[] {typeof (string)});
Expression[] parms = new Expression[]{right, Expression.Parameter(typeof(Enum) , "StringComparison.OrdinalIgnoreCase")};
var exp =  Expression.Call(left, methodCall, parms);
return exp;

Bitte denken Sie daran, dass es funktioniert, wenn ich den Parameter OrdinalIgnoreCase ignoriere.

Vielen Dank

Akzeptierte Antwort

Ich vermute, dass es zwei Probleme gibt.

Der erste ist die Methode, mit der Sie die Methode erhalten. Sie fragen nach einer Methode mit nur einem einzigen String-Parameter anstelle eines Parameters mit zwei Parametern:

var methodCall = typeof (string).GetMethod("IndexOf",
                            new[] { typeof (string), typeof(StringComparison) });

Der zweite Wert ist der Wert, den Sie angeben. Es sollte der tatsächliche Wert der Konstante sein, nicht ein String:

Expression[] parms = new Expression[] { right, 
    Expression.Constant(StringComparison.OrdinalIgnoreCase) };

EDIT: Hier ist ein komplettes funktionierendes Beispiel:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main()
    {
        var method = typeof (string).GetMethod("IndexOf",
                new[] { typeof (string), typeof(StringComparison) });

        var left = Expression.Parameter(typeof(string), "left");
        var right = Expression.Parameter(typeof(string), "right");

        Expression[] parms = new Expression[] { right, 
                Expression.Constant(StringComparison.OrdinalIgnoreCase) };

        var call = Expression.Call(left, method, parms);
        var lambda = Expression.Lambda<Func<string, string, int>>
            (call, left, right);

        var compiled = lambda.Compile();
        Console.WriteLine(compiled.Invoke("hello THERE", "lo t"));
    }
}

Beliebte Antwort

Der einfachste Weg wäre, es über ein Lambda zu erhalten:

//the compiler will convert the lambda into an expression
Expression<Func<string, string, int>> expression = (s1, s2) => s1.IndexOf(s2, StringComparison.OrdinalIgnoreCase);
//compile the expression so we can call it
var func = expression.Compile();
//outputs 2
Console.WriteLine(func("Case Sensitive", "se sensitive"));

Dies ist viel besser lesbar und wartbar als das manuelle Erstellen einer Ausdrucksbaumstruktur.

Ich bin ständig überrascht von der Menge an Leuten, die direkt in den manuellen Aufbau von Ausdrucksbäumen eintauchen. Es gibt keine Notwendigkeit, wenn Sie den Compiler dazu bringen können, die Arbeit für Sie zu erledigen.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow