Eine andere Lösung ist ExpressionVisitor
zu verwenden, um die Parameter in der rechten Ausdruck mit der gesamten linken Ausdruck, mit anderen Worten zu ersetzen, die linke in die rechte einbetten.
Ausdruck Besucher wird ziemlich einfach sein, benötigte Daten zum Konstruktor hinzufügen, überschreiben eine Methode und das ist alles.
Es kann ziemlich einfach erweitert werden, um Sammlungen von Ausdrücken im Konstruktor zu behandeln, aber ich hielt es kurz.
Jetzt müssen Sie es nur für die Ausdruckskörper verwenden und neues Lambda erstellen.
private static Expression<Func<TIn, TOut>> Merge<TIn, TInter, TOut>(Expression<Func<TIn, TInter>> left, Expression<Func<TInter, TOut>> right)
{
var merged = new ParameterReplaceVisitor(right.Parameters[0], left.Body).Visit(right.Body);
var lambda = Expression.Lambda<Func<TIn, TOut>>(merged, left.Parameters[0]);
return lambda;
}
Getestet habe ich es auf diesem Code:
Expression<Func<string, int>> l = s => s.Length + 5;
Expression<Func<int, string>> r = i => i.ToString() + " something";
var merged = Merge(l, r);
var res = merged.Compile()("test");
und das Ergebnis ist wie erwartet: 9 something
.
BEARBEITEN: Wenn Leistung ist Ihr Anliegen, warum verwenden Sie Ausdrücke anstelle von einfach Func
s? Dann könntest du nur nacheinander anrufen. Werden die Expressionsbäume später analysiert?
Danke! Wie kann ich das optimieren? Leistung ist in diesem speziellen Fall kritisch. –
Ich modifizierte Antwort – LmTinyToon
Die zweite vorgeschlagene Lösung schafft Delegierte und anonyme Objekte, die ich würde sagen, ist nicht sehr gut in Bezug auf die Leistung .. oder fehlt mir etwas? –