Laden...

Methode aus dem .NET Framework anpassen/erweitern/verändern

Erstellt von zommi vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.055 Views
zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 13 Jahren
Methode aus dem .NET Framework anpassen/erweitern/verändern

Hallo,

ich benutze zur Zeit die Methode Expression<TDelegate>.Compile(), hab aber Probleme mit einem Implemetierungsdetail.

Im Funktionsaufrufbaum dieser Methode wird irgendwann (beim System.Linq.Expressions.Compiler.LambdaCompiler) eine DynamicMethod erzeugt.

Ich möchte nun gern einen Parameter bei dem DynamicMethod-Konstruktor verändern (bzw. einen anderen der Konstruktoren aufrufen).
Wie könnte ich nun ganz tief drin so eine Änderung umsetzen?!?

Meine bisherigen Ideen:*Kompletten Code des System.Linq.Expressions.Compiler-Namespaces der System.Core.dll mit dem .Net-Reflector disassemblieren, verändern, neu übersetzen und diese andere Bibliothek nutzen. (lizenzrechtlich problematisch?) *Mittels Reflection den Funktionsaufrufbaum bis zur nötigen Tiefe "nachprogrammieren". Ich schau mir wieder mit dem Reflector an, was Funktion x macht und baue das mit Reflections-Aufrufen nach. Reflection ist hier nötig, weil viel davon private/internal ist, weshalb ich nicht direkt mit den Typen und Feldern arbeiten kann. *Ich manipulier irgendwie direkt den IL-Code sodass nicht der eigentliche Konstruktor sondern ne andere Methode (von mir) aufgerufen wird. Aber werden die System.Core.dll-Methoden überhaupt erst noch geJITtet? Sind die nicht schon vorkompiliert?

Ich hoffe ihr könnt mir mit ein paar Tipps helfen.

beste Grüße
zommi

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

Aber werden die System.Core.dll-Methoden überhaupt erst noch geJITtet?

Die liegt im GAC und is NGened, da wird nichts mehr geJITet.

Unter der Annahme dass Mono den System.Linq.Expressions.Compiler-Namespace auch bietet kannst du dir von dort den Source holen und ändern (also dein 1. Punkt nur auf Mono angewandt). Ich denke das wäre es auch lizenzrechtlich OK (zumindest lockerer als bei MS 😉

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 13 Jahren

Hi,

Die liegt im GAC und is NGened, da wird nichts mehr geJITet.

Sowas hatte ich befürchtet. Dann wird das aufwändiger...

Unter der Annahme dass Mono den System.Linq.Expressions.Compiler-Namespace auch bietet kannst du dir von dort den Source holen und ändern (also dein 1. Punkt nur auf Mono angewandt).

Das mit Mono ist ne gute Idee. Nen ExpressionTree -> DynamicMethod Compiler haben die auch. Aber ich hab ihn jetzt noch nicht weiter getestet.

Ich habe mich jetzt erstmal für Variante b) entschieden. Das war ziemlich straightforward umzusetzen.
Also mit dem Reflector gucken, was da abgeht und das durch Reflection-Aufrufe mit vielen FieldInfo's, ConstructorInfos und etlichen Invokes "nachprogrammiert".
Funktioniert einwandfrei! 🙂
.NET Framework has officially been pimped! 8)

Wem sonst noch schöne Varianten (weil sooo schön is der Weg jetzt nich) einfallen - immer her damit 😉

beste Grüße
zommi

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo zommi,

hast du auch Erfahrung mit Mono.Cecil (also dem "Gegenstück" zu MS-Reflection)? Das soll sich ja gut dafür eignen. Ich hab nur darüber gelesen, aber keine praktische Erfahrung damit.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

5.941 Beiträge seit 2005
vor 13 Jahren

Salute zommi

Hmm, sowas müsste doch eigentlich ohne Änderung des Frameworks möglich sein.
Entweder arbeitest du direkt mit DynamicMethod, ohne Expression Trees, oder aber du fügst deine gewünschte DynamicMethod in den Expression-Tree als Konstante rein (Expression.Constant).

Ansonsten wäre ein Beispiel deiner versuchten Anwendung nützlich.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 13 Jahren

Hi,

@gfoidl
Mh.. Mono.Cecil schaut schick aus. Hab mich jetzt erstmals etwas damit beschäftigt.

@Peter Bucher

Entweder arbeitest du direkt mit DynamicMethod, ohne Expression Trees

Dann müsste ich mich aber mit IL-OpCodes herumschlagen. 😜 Und ich würde gern in ExpressionTrees denken und nicht in IL-Code. 😉

oder aber du fügst deine gewünschte DynamicMethod in den Expression-Tree als Konstante rein (Expression.Constant).

Genau andersrum soll es ein. Der ExpressionTree steht für eine Methode. Und diesen ExpressionTree möchte ich gern als eine DynamicMethod kompilieren lassen, damit ich ihn aufrufen kann. Ich hoffe, so ists verständlich 🤔

Das bietet prinzipiell die LambdaExpression.Compile()-Methode an. Allerdings macht die intern etwas, was mir nicht gefällt. Daher das Verlangen, im Framework rumzufummeln.
Und das Rumfummeln soll aber trotzdem elegant sein. Daher mein Suche nach schönen Möglichkeiten und dieser Post hier. =)

Das was mir daran nicht gefallen hat, war ein Default-Parameter, der sich sehr sehr schlecht auf die Performance auswirkt. Wer möchte, kann dazu auf meinem Blog im Post DynamicMethod vs. DynamicAssembly einiges nachlesen.

beste Grüße
zommi

2.891 Beiträge seit 2004
vor 13 Jahren

Hallo zommi,

hast du dir mal Moles angeguckt?

Zitat von: Moles - Isolation framework for .NET - Microsoft Research
Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types.


// DateTime.Now auf eigenes Delegat umleiten
MDateTime.NowGet = () => new DateTime(2000,1,1);

if (DateTime.Now == new DateTime(2000,1,1))
   throw new Y2KBugException(); // puff!

Damit solltest du (theoretisch) den "falschen" Aufruf durch deinen eigenen Delegaten ersetzen können. Wäre halt nur zu klären, inwieweit das Ganze außerhalb einer (Unit)Testumgebung einsetzbar ist.

Gruß,
dN!3L

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

Wäre halt nur zu klären, inwieweit das Ganze außerhalb einer (Unit)Testumgebung einsetzbar ist.

Wohl kaum bis gar nichts. Soweit ich des seh muss immer der Pex Profiler attached sein, da er über das Attribut dann zur Laufzeit den Code entsprechend instrumentiert damit die benutzerdefinierten Delegates ausgeführt werden. Sowas kann man in einer Produktivumgebung kaum machen. Zumal auch die Doku von signifikanten Performanceverschlechterungen spricht. Nichtsdestotrotz ist Moles für seinen eigentlichen Anwendungszweck natürlich ne sehr interessante Sache.

Baka wa shinanakya naoranai.

Mein XING Profil.

2.891 Beiträge seit 2004
vor 13 Jahren

Soweit ich des seh muss immer der Pex Profiler attached sein,[...] Zumal auch die Doku von signifikanten Performanceverschlechterungen spricht.

Hm, stimmt. Wenn das ganze über die .NET Profiling API läuft, wird es nicht gerade die Ziele von zommi treffen 😉
@zommi: Du hattest doch selbst mal was gebastelt, um bestimmte Calls im IL durch einen eigenen Delegaten zu ersetzen. Ist das hier nicht anwendbar?

Gruß,
dN!3L

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 13 Jahren

Hallo,

danke erstmal für die Ideen. Moles is cool 😉 Aber mit attached Debugger/Profiler dran, wollt ichs wirklich nich laufen lassen 😉

@dN!3L

Du hattest doch selbst mal was gebastelt, um bestimmte Calls im IL durch einen eigenen Delegaten zu ersetzen. Ist das hier nicht anwendbar?

Ich hatte bei Fast and Simple Bitmap Filter eine neue Methode erzeugt, den IL-Code manipuliert und danach JITten lassen.

Insofern wird das hier nicht anwendbar sein, denn:

Aber werden die System.Core.dll-Methoden überhaupt erst noch geJITtet? Sind die nicht schon vorkompiliert?
Die liegt im GAC und is NGened, da wird nichts mehr geJITet.

beste Grüße
zommi

2.891 Beiträge seit 2004
vor 13 Jahren

Insofern wird das hier nicht anwendbar sein, denn: [...] Die liegt im GAC und is NGened, da wird nichts mehr geJITet.

Sorry, wenn ich noch auf dem Schlauch steh, aber: Du hast die entsprechende Methode doch disassembliert und kommst somit auch an den IL-Code. Warum kann dein Tool das nicht entsprechend machen?

Gruß,
dN!3L

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 13 Jahren

Hi,

weil in meinem Tool immer eine (modifizierte) Kopie erzeugt wurde. Ich habe nie eine fertige Methode ersetzt. Immer nur eine bestehende genommen, den IL-Code genommen, manipuliert und eine neue erzeugt. Die alte bleibt gleich.

Und die eigentliche Methode bekomm ich damit also nicht ersetzt. Selbst mit der
MethodRental-Klasse kann ich nicht im Framework wuseln.

Zitat von: msdn
The method can only be called by the client that created the dynamic module that contains the type whose method's body is being swapped.

beste Grüße
zommi