2008-10-30 4 views
12

Ich weiß, dass es theoretisch möglich ist, einen neuen Typ zur Laufzeit zu erstellen, aber ist es möglich, einen Methodenrumpf eines vorhandenen Typs zur Laufzeit zu ändern? Mein Plan (wenn ich das zum Laufen bringen kann) besteht darin, Methoden mit einem benutzerdefinierten Attribut zu markieren und dann zur Laufzeit nach Methoden mit dem Attribut zu suchen und einen Teil meines eigenen Codes in den Methodenkörper einzufügen.Ist es möglich, einen Methodenkörper zur Laufzeit in .NET zu ändern?

Irgendwelche Vorschläge?

Ich denke, wenn ich diesen Ansatz nicht zum Laufen bringen kann, könnte ich immer mit einer virtuellen Methode in einer Basisklasse (mit den Attributen) in Kombination mit einer statischen Factory einen abgeleiteten dynamischen Typ mit meinem Lauf ausspucken -time generierte Methode in der Kindklasse. Dies wäre jedoch nicht ganz so sauber zu verwenden.

Antwort

9

PostSharp die ein aftercompiler ist, tut etwas Ähnliches, was Sie beschreiben, Attribute mit Injektionsstellen im Code markieren Der einzige Unterschied ist, dass es zur Kompilierungszeit ausgeführt wird.

Sie können es aber auch zur Laufzeit tun, indem Sie nicht die Methodenkörper ändern, sondern Klassen verwenden, die von ContextBoundObject abgeleitet sind. Dies ist eine .NET-Klasse, mit der Sie alle Aufrufe abfangen können. Hier ist eine MSDN Magazine article beschreibt, wie AOP mit ContextBoundObject zu tun. (Schauen Sie sich die Aspekte in .Net Teil des Artikels)

Und als dritte Option können Sie dynamische Code-Generierung (Reflection.Emit oder CodeDom) verwenden in Kombination mit Attributen und virtuellen Methoden dynamisch abgeleitete Klassen zu generieren, wo Sie kann Ihren Code einfügen, aber das ist die schmerzhafteste Art, dies zu tun.

Edit:

Es gibt eine vierte Option .Net unmanaged profiling API zu verwenden Methode JIT-ing abzufangen und Methodenrümpfe vor JIT-ing zu ersetzen. Diese Technik wird von JustMock (Telerik) erfolgreich verwendet, um statische Methoden, nicht-virtuelle Methoden und sogar versiegelte Klassen zu verspotten.

0

Haben Sie vor, dies für beliebige Typen zu tun? Ich nehme nicht an, dass Sie die Methoden mit einem Attribut versehen werden.

Vor diesem Hintergrund würde ich denken, der bessere Ansatz wäre, abstrakte Methoden in einer Superklasse für Ihre Typen zu definieren. Eine Methode für die Superklasse kann den Methodencode des Kesselblechs aufnehmen und über die abstrakten Methoden für das Verhalten des einzelnen Typs an die konkreten Implementierungen delegieren.

Im Allgemeinen, wenn Sie nicht in Code-Dateien erstellen und dynamische Assemblys zur Laufzeit kompilieren, was Sie suchen, kann nicht getan werden. Es gibt wahrscheinlich weit mehr praktische OO-Prinzipien und Muster, die Sie verwenden können, um nahezu das gleiche Ergebnis zu erzielen.

3

Sie können eine vorhandene Methode zur Laufzeit nicht ändern, aber Sie können eine mit Code-DOM im Handumdrehen erstellen und diese ausführen. Oder Sie könnten Zeichenketten zusammenfassen und im Speicher kompilieren und ausführen.

Ich habe das letztere selbst gemacht (eine App, die ich benutzerdefinierte C# -Code erlaubt hatte, die im Speicher kompiliert und ausgeführt wurde, Laufzeit).