Linq Ausdruck Tree String Vergleich

expression-trees linq

Frage

Ich versuche, einen Ausdrucksbaum zu konstruieren, der gegen ein Zeichenfolgenarray arbeitet. Ich muss herausfinden, wie man die Equal-Methode benutzt.

Kann mir jemand ein Beispiel geben?
1) Verwenden der Expression.Equal (oder .Equals) -Methode, um eine Zeichenkette mit einer Konstanten zu vergleichen, und
2) Verwenden eines Ausdrucks beliebiger Art, um die Methode string.Contains () zum Filtern zu verwenden.

Ich versuche, die Expression Tree-Mechanik zu lernen, aber bis jetzt habe ich noch kein gutes Tutorial gefunden. Ich schätze Ihre Hilfe sehr.

string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();

// what should go below here?
ParameterExpression p1 = Expression.Parameter(typeof(string), "c");
Expression left = Expression.Constant("s2");
Expression e1 = Expression.Equal(left, p1);

IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);

Akzeptierte Antwort

Aaah, ich sehe was du fragst ... Und du betrittst wirklich sehr düstere Gewässer, eines der wenigen Gebiete, mit denen die .NET Reflektionsbibliotheken nicht schön sind. Sie müssen einen Aufrufausdruck erstellen, um Queryable.Where () im queryableData-Objekt aufzurufen, und eine neue Abfrage mit diesem Ausdruck erstellen ... Das Problem besteht darin, dass das Abrufen einer generischen Version einer Methode in .NET nicht unbedingt die einfachste ist was du jemals in deinem Leben erlebt hast:

MethodCallExpression call = Expression.Call(
    null, // Calling Queryable.Where(), extension method, not instance method
    getGenericMethod<string>(typeof(Queryable), "Where", typeof(IQueryable<string>), typeof(Expression<Func<string,bool>>)),
    Expression.Constant(queryableData),
    Expression.Lamda(
       e1,
       p1)
);
IQueryable<string> res = queryableData.Provider.CreateQuery<string>(call);

Sie müssten auch getGenericMethod definieren (Sie können bessere Implementierungen für diese online an anderen Orten finden, das ist wirklich ein ziemlich einfacher Ansatz):

private static MethodInfo getGenericMethod<T>(Type type, string name, params Type[] paramTypes)
{
    MethodInfo[] methods = type.GetMethods(name);
    foreach(MethodInfo mi in methods)
    {
        if(!mi.IsGenericMethodDefinition) // or some similar property
            continue;
        if(mi.GetGenericArguments().Length != 1)
            continue;
        if(mi.GetParameters().Length != paramTypes.Length)
            continue;


        MethodInfo genMethod = mi.MakeGenericMethod(new Type[]{typeof(T)});
        var ps = genMethod.GetParameters();
        bool isGood = true;
        for(int i = 0; i < ps.Length; i++)
        {
            if(ps[i].ParameterType != paramTypes[i])
            {
               isGood = false;
               break;
            }
        }

        if(isGood)
            return genMethod;

    }

    return null;
}

Es sind fast sicher ein paar Fehler drin, aber ich hoffe, du kannst sehen, wohin du von dort gehst ...


Beliebte Antwort

Nur um meine Lösung zu geben:

string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();
ParameterExpression pe = Expression.Parameter(typeof(string), "company");
Expression right = Expression.Constant("on");
Expression left = Expression.Call(pe, typeof(string).GetMethod("Contains"), right);
MethodCallExpression e2 = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { queryableData.ElementType },
            queryableData.Expression,
            Expression.Lambda<Func<string, bool>>(left, new ParameterExpression[] { pe }));

IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum