Wie komme ich von ConditionalExpression.IfThen in Baum mit MethodCallExpression / Lambda?

c# expression-trees linq

Frage

Ich versuche, einen Ausdrucksbaum zu erhalten, der bedingt zu einer Schnur auswertet.

Hier ist mein Code soweit:

IQueryable<Category> myCategories = DataUtil.Categories.AsQueryable();

ParameterExpression categoryParameterExpression = Expression.Parameter(typeof (Category), "category");
MemberExpression categoryNameMemberExpression = Expression.PropertyOrField(categoryParameterExpression, "CategoryName");
MemberExpression categoryNameLengthExpression = Expression.Property(categoryNameMemberExpression, typeof (string).GetProperty("Length"));
ConstantExpression constantLengthExpression = Expression.Constant(10, typeof (int));
BinaryExpression greaterThanLengthExpression = Expression.GreaterThan(categoryNameLengthExpression, constantLengthExpression);
var getNameInCapsMethod = typeof (Category).GetMethod("GetNameInCaps", BindingFlags.Instance | BindingFlags.Public);
MethodCallExpression getNameInCapsExpression = Expression.Call(categoryParameterExpression, getNameInCapsMethod, categoryNameMemberExpression);

ConditionalExpression ifGreaterThanLengthGetUpperNameExpression = Expression.IfThen(greaterThanLengthExpression, getNameInCapsExpression); 

// I need something between the lambda and the ConditionalExpression to ensure that the void type is not returned?

var ifGreaterThanLengthGetUpperNameLambdaExpression = Expression.Lambda<Func<Category, string>>(ifGreaterThanLengthGetUpperNameExpression, new ParameterExpression[] { categoryParameterExpression }); 
foreach (var category in myCategories)
{
    var upperName = ifGreaterThanLengthUpperLambda(category);
    System.Windows.MessageBox.Show(upperName);
}

Hier ist die ArgumentException, die zur Laufzeit auftritt:

Eine nicht behandelte Ausnahme vom Typ "System.ArgumentException" ist in System.Core.dll aufgetreten

Weitere Informationen: Der Ausdruck 'System.Void' kann nicht für den Rückgabetyp 'System.String' verwendet werden.

Ich habe herausgefunden, dass ConditionalExpression den void-Typ für die "IfFalse" -Bedingung zurückgibt.

Hier ist der Screenshot von meinem Expression Tree Visualizer: ConditionalExpression gibt void zurück

Ich möchte nur den String-Wert. Ich merke, dass es einen Expression.IfThenElse für den ConditionalExpression-Typ gibt, aber ich bin mir nicht sicher, was ich in den Else-Ausdruck schreiben soll. (Ich möchte, wenn möglich, nicht einfach eine leere Zeichenfolge zurückgeben.) Gibt es eine Möglichkeit für mich, sicherzustellen, dass die Bedingung nur ausgewertet wird, wenn der vorhergehende BinaryExpression als wahr ausgewertet wird? Egal, wie löse ich dieses Problem?

Akzeptierte Antwort

Es wäre wahrscheinlich hilfreich, genauer auszudrücken, was Sie wirklich erreichen möchten (im Wesentlichen, wie das C # -Äquivalent Ihres gewünschten Ausdrucksbaums aussehen würde). Ihr Ausdrucksbaum sieht im Moment ungefähr so ​​aus:

Func<Category, string> f = (category) => { 
    if (category.CategoryName.Length > 10) {
        category.GetNameInCaps(category.CategoryName);
    }
};

Der C # -Compiler kompiliert dies jedoch nicht, da Sie keine Zeichenfolge für einen der Codepfade zurückgeben. Es ist also kein Wunder, dass die Ausdrucksstruktur nicht wie gewünscht kompiliert wird. Es gibt mindestens zwei Probleme:

  1. Sie möchten fast sicher eine Expression.Condition anstelle von Expression.IfThen . Dies gibt Ihnen das Äquivalent des ... ? ... : ... Syntax in C #. Dies ist ein Ausdruck, der als Rückgabewert für Ihr Lambda verwendet werden kann. Als eine Anweisung hat ein if (...) { } -Block immer den Typ void , wie Sie gefunden haben (und dies wäre auch dann wahr, wenn Sie ein else hinzufügen).
  2. Sie müssen herausfinden, was zu tun ist, wenn Ihr Zustand nicht hält. Wenn Sie wirklich eine Zeichenfolge zurückgeben müssen, müssen Sie entweder
    • Wählen Sie einen Standardwert ohne Bedeutung, der zurückgegeben werden soll (z. B. null oder "" ), oder
    • Eine Ausnahme auslösen


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