Ich suche nach einer Möglichkeit, zwei Lambda-Ausdrücke zu kombinieren, ohne einen Expression.Invoke
auf einen der beiden Ausdrücke zu verwenden. Ich möchte im Wesentlichen einen neuen Ausdruck erstellen, der zwei getrennte kettet. Betrachten Sie den folgenden Code:
Und sagen wir, ich hätte zwei Ausdrücke:
%Vor%Und ich möchte sie zusammenfügen, um funktionell den folgenden Ausdruck zu erhalten:
%Vor%Der einzige Weg, um dies zu tun, ist, einen ExpressionVisitor wie folgt zu verwenden:
%Vor%Und dann wird es so benutzt:
%Vor%Es funktioniert, aber es fühlt sich ein bisschen klobig an. Ich versuche immer noch, meinen Kopf einzudrücken und mich zu fragen, ob es eine idiomatische Art gibt, das auszudrücken, und ich habe den hinterhältigen Verdacht, dass ich etwas Offensichtliches vermisse.
Der Grund Ich möchte dies mit den ASP.net mvc 3 Html-Helfern machen. Ich habe einige tief verschachtelte ViewModels und einige HtmlHelper-Erweiterungen, die helfen, mit diesen umzugehen. Daher muss der Ausdruck nur eine Sammlung von MemberExpressions
für die eingebauten MVC-Helfer sein, um sie korrekt zu verarbeiten und korrekt tief verschachtelte Namensattributwerte zu erstellen. Mein erster Instinkt war, Expression.Invoke()
zu verwenden und den ersten Ausdruck aufzurufen und ihn mit dem zweiten zu verketten, aber die MVC-Helfer haben das nicht sehr gemocht. Es hat seinen hierarchischen Kontext verloren.
Verwenden Sie einen Besucher, um alle Instanzen des Parameters f
auf m.SubModel.Foo
zu tauschen, und erstellen Sie einen neuen Ausdruck mit m
als Parameter:
Ihre Lösung scheint eng auf Ihr spezifisches Problem zugeschnitten zu sein, das unflexibel scheint.
Es scheint mir, dass Sie Ihr Problem einfach durch einfache Lambda-Substitution lösen können: Ersetzen Sie Instanzen des Parameters (oder "freie Variable", wie sie es im Lambda-Kalkül nennen) durch den Körper. (Siehe Marcs Antwort für einen bestimmten Code.)
Da Parameter in Ausdrucksbäumen referenzielle Identität und nicht Wertidentität haben, ist es nicht einmal notwendig, sie umzubenennen.
Das heißt, Sie haben:
%Vor%und Sie möchten die Komposition
erstellen %Vor% Nimm den Körper g(b)
, suche einen Besucher und suche ihn nach dem ParameterExpression
für b
und ersetze ihn durch den Körper f(a)
, um dir den neuen Körper g(f(a))
zu geben. Dann erstellen Sie ein neues Lambda mit dem Parameter a
, der diesen Körper hat.
Update: Die folgende Antwort generiert eine "Invoke", die EF nicht unterstützt.
Ich weiß, dass dies ein alter Thread ist, aber ich habe das gleiche Bedürfnis und ich habe einen saubereren Weg gefunden, es zu tun. Angenommen, Sie können Ihr "expression2" ändern, um ein generisches Lambda zu verwenden, können Sie eines wie folgt injizieren:
%Vor%Tags und Links asp.net-mvc-3 c# expression-trees