konvertieren eines .net-Func - <T> ein .net-Ausdruck<U<T>>
Geht aus einem lambda-Ausdruck ein Ausdruck ist einfach über einen Aufruf der Methode...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; //"DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
Aber ich würde gerne die Func in einem Ausdruck, nur in seltenen Fällen...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
//This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Die Zeile, die nicht arbeiten, gibt mir die compile-Zeit-Fehler Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'
. Eine explizite Umwandlung löst nicht die situation. Besteht die Möglichkeit, das zu tun, ich bin mit Blick?
Sehe ich nicht wirklich viel Verwendung für die "seltenen Fall" Beispiel. Der Aufrufer übergibt die Func - <T>. Es gibt keine Notwendigkeit, zu wiederholen, an den Aufrufer zurück, was das Func<T> (über die Ausnahme).
Die Ausnahme nicht behandelt, in der Anrufer. Und, weil es mehrere call-sites übergeben in verschiedenen Func<T>s, fangen Sie die Ausnahme in der Anrufer schafft Doppelarbeit.
Die Ausnahme-stack-trace wird konstruiert, um zu zeigen, diese Informationen. Wenn die exception geworfen wird in dem Aufruf der Func - <T>, dies wird show in der Stapel-Ablaufverfolgung. Übrigens, wenn Sie zu wählen, in die andere Richtung gehen, D. H. einen Ausdruck akzeptieren und kompilieren es für den Aufruf, würden Sie diese verlieren, da der stack-trace, die zeigen würde, so etwas wie
Ich denke, Sie sollten sich auf die Antwort in diesem [link][1] [1]: stackoverflow.com/questions/9377635/create-expression-from-func/...
Die Ausnahme nicht behandelt, in der Anrufer. Und, weil es mehrere call-sites übergeben in verschiedenen Func<T>s, fangen Sie die Ausnahme in der Anrufer schafft Doppelarbeit.
Die Ausnahme-stack-trace wird konstruiert, um zu zeigen, diese Informationen. Wenn die exception geworfen wird in dem Aufruf der Func - <T>, dies wird show in der Stapel-Ablaufverfolgung. Übrigens, wenn Sie zu wählen, in die andere Richtung gehen, D. H. einen Ausdruck akzeptieren und kompilieren es für den Aufruf, würden Sie diese verlieren, da der stack-trace, die zeigen würde, so etwas wie
at lambda_method(Closure )
für den Aufruf der kompilierten delegieren.Ich denke, Sie sollten sich auf die Antwort in diesem [link][1] [1]: stackoverflow.com/questions/9377635/create-expression-from-func/...
InformationsquelleAutor Dave Cameron | 2009-04-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ooh, es ist gar nicht einfach.
Func<T>
stellt eine generischedelegate
und nicht Ausdruck. Wenn es irgendeine Weise, die Sie tun könnte (aufgrund von Optimierungen und andere Dinge, die erledigt der compiler, einige Daten könnten weggeworfen werden, so kann es unmöglich sein, um die ursprünglichen Ausdruck zurück), es wäre die Demontage der IL auf die fliege und die Herleitung des Ausdrucks (was keineswegs einfach ist). Die Behandlung von lambda-Ausdrücken als die Daten (Expression<Func<T>>
) ist eine Magie, die geschieht durch die compiler (im Grunde der compiler baut einen Ausdruck-Baum im code, kompilieren Sie es, um IL).Verwandte Tatsache
Dies ist der Grund, warum Sprachen, die push-lambdas zu den extremen (wie Lisp) sind oft einfacher zu implementieren, als Dolmetscher. In jenen Sprachen, die code und Daten sind im wesentlichen das gleiche (auch bei Laufzeit), aber unser chip kann nicht verstehen, dass form-code, so haben wir zu emulieren, wie eine Maschine durch den Aufbau eines Dolmetscher auf der Oberseite der es versteht, Sie (die Wahl von Lisp wie Sprachen) oder auf die Leistung (code nicht mehr genau gleich der Daten) zu einem gewissen Grad (die Wahl von C#). In C# der compiler gibt die illusion der Behandlung von code als Daten, indem Lambda-Ausdrücke interpretiert werden als code (
Func<T>
) und Daten (Expression<Func<T>>
) bei compile-Zeit.eval
würden Sie brauchen, um starten Sie den compiler, aber anders als das, es ist überhaupt kein problem das zu tun."Ausdruck<U<T>> DangerousExpression = () => dangerousCall();" ist nicht einfach?
Schaffen würde, die neue
Expression
über Ihre wrapper-Aktion, aber es hätte keine expression tree info über InternadangerousCall
delegieren.InformationsquelleAutor Mehrdad Afshari
Nein. Siehe oben Antworten - die bereits kompilierten
Func
wird versteckt in einem new-Ausdruck. Dies fügt einfach eine Schicht von Daten über code; könnten Sie durchqueren einer Schicht, die nur zu finden, Ihre parameterf
ohne weitere details, so dass Sie sind da, wo Sie gestartet.Jono ist Recht, das nicht helfen, OP..
Das wird nicht funktionieren, wie beschrieben in den anderen Antworten.
InformationsquelleAutor Override
Was Sie wahrscheinlich tun sollten, ist wiederum die Methode um. Nehmen Sie in einem Ausdruck>, und kompilieren und ausführen. Wenn es ausfällt, Sie haben bereits den Ausdruck in.
Natürlich müssen Sie berücksichtigen die Auswirkungen auf die Leistung, und bestimmen, ob es etwas, was Sie wirklich tun müssen.
InformationsquelleAutor David Wengier
Können Sie gehen den anderen Weg über die .Compile () - Methode jedoch nicht sicher, ob dies für Sie sinnvoll ist:
InformationsquelleAutor Steve Willcock
Können Sie erläutern, wie die "das wird nicht funktionieren" - Teil? Haben Sie tatsächlich versucht zu kompilieren und es auszuführen? Oder es funktioniert nicht, besonders in Ihrer Anwendung?
FWIW, dies könnte nicht das sein, was die main-ticket war, aber es war, was ich brauchte. Es war die
call.Target
Teil, der mich fertigmachte. Es funktionierte jahrelang, und dann plötzlich aufgehört zu arbeiten und begann zu Klagen über eine statische/nicht-statische, blah, blah. Trotzdem, vielen Dank!InformationsquelleAutor Dmitry Dzygin
NJection.LambdaConverter ist eine Bibliothek, konvertiert der Delegierten zum Ausdruck
InformationsquelleAutor Sagi
Wenn Sie manchmal brauchen, ein Ausdruck und manchmal müssen Sie einen Delegaten, haben Sie 2 Möglichkeiten:
Expression<...>
version, und nur.Compile().Invoke(...)
es, wenn Sie möchten, eine Stellvertretung. Offensichtlich ist dies gekostet hat.InformationsquelleAutor Marc Gravell
JB Evain von Cecil Mono-team ist dabei einige Fortschritte erzielt, um dies zu ermöglichen
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
InformationsquelleAutor aaguiar
Ändern
Zu
InformationsquelleAutor mheyman