Boolesche Bedingung in Ausdrucksbaumstruktur analysieren

c# expression-trees linq

Frage

Wenn ich eine Methode habe, die einen booleschen Wert annimmt:

public void Foo(boolean condition)

Und nenne es so:

Foo("MyField" == "MyValue");

Kann ich das in einen Ausdrucksbaum schreiben, um eine Abfrage zu einer anderen Datenquelle zu erstellen, die MyField als einen Parameter und MyValue und einen anderen verwendet. Ich kann diese Bedingung nur zu einem Ausdruck machen, der sich als falsch herausstellt.

AKTUALISIEREN

    var param = Expression.Parameter(typeof(Field), field);
    var prop = Expression.PropertyOrField(param, "Name");

    ConstantExpression @const = Expression.Constant(value, typeof(string));
    var body = Expression.Equal(prop, @const);
    var lambda = Expression.Lambda<Func<Field, bool>>(body, param);

Wobei Field eine Klasse mit zwei Eigenschaften ist, Name und Wert

Akzeptierte Antwort

Foo("MyField" == "MyValue") ist, wie am Ende der Frage angemerkt, eine Konstante false (direkt beim Compiler). Sie haben hier ein paar Möglichkeiten - am einfachsten ist es natürlich, etwas zu tun wie:

void Foo(Expression<Func<YourType,bool>> predicate) {...}

und ruf mit an

Foo(x => x.MyField == "MyValue");

dann ist hier nichts mehr zu tun; wir haben schon den Ausdruck. Ich nehme an, Sie meinen "MyField" ist eine Zeichenfolge, die nur zur Laufzeit bekannt ist, in diesem Fall:

void Foo<T>(string fieldName, T value) {
   var param = Expression.Parameter(typeof(YourType), "x");
   var body = Expression.Equal(
                  Expression.PropertyOrField(param, fieldName),
                  Expression.Constant(value, typeof(T))
               );
   var lambda = Expression.Lambda<Func<YourType, bool>>(body, param);
}

und rufe mit Foo("MyField", "MyValue) (mit einer impliziten <string> da, mit freundlicher Genehmigung des Compilers), oder Foo("MyField", 123) wenn die prop ein int (implizit <int> ),

Das letzte Szenario ist, wo "MyValue" ist auch eine Zeichenfolge nur zur Laufzeit bekannt (emph: string ) - in diesem Fall müssen wir es analysieren:

void Foo(string fieldName, string value) {
   var param = Expression.Parameter(typeof(YourType), "x");
   var prop = Expression.PropertyOrField(param, fieldName);
   ConstantExpression @const;
   if(prop.Type == typeof(string)) {
       @const = Expression.Constant(value, typeof(string));
   } else {
       object parsed = TypeDescriptor.GetConverter(prop.Type)
           .ConvertFromInvariantString(value);
       @const = Expression.Constant(parsed, prop.Type);
   }
   var body = Expression.Equal(prop,@const);
   var lambda = Expression.Lambda<Func<YourType, bool>>(body, param);
}

Hier ist der Aufruf immer 2 Strings - also Foo("MyField", "123") auch wenn int .


Beliebte Antwort

In kann Ausdrucksbäume von Delegaten erstellen. Wenn Sie beispielsweise Ihre Methode so definieren, dass sie einen Delegaten als Parameter akzeptiert, können Sie ihn wie folgt verwenden:

public void Foo(Func<bool> fn)
{
    // invoke the passed delegate
    var result = fn();
}

Foo(() => "MyField" == "MyValue");

Um einen Ausdrucksbaum zu erstellen, anstatt den Delegaten auszuführen, ändern Sie die Methode wie folgt:

public void Foo(Expression<Func<bool>> expression)
{
   // inspect your expression tree here
}

In Ihrem Fall werden Sie jedoch feststellen, dass Ihr Ausdruck eine boolesche Konstante mit dem Wert 'false' ist, da der Compiler "MyField" == "MyValue" ausgewertet hat, was natürlich falsch ist.

Wenn Sie nur Name-Wert-Paare wollen, die nicht nur ein Dictionary<string, string> ?



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