Laden...

Methode mit Reflection austauschen

Erstellt von SimonKnight6600 vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.972 Views
S
SimonKnight6600 Themenstarter:in
709 Beiträge seit 2005
vor 15 Jahren
Methode mit Reflection austauschen

Hallo zusammen!

Wir verwenden hier in einer Firma eine Komponente, die wir an einer bestimmten Stelle erweitern wollen. Allerdings ist diese Komponente dazu keine Möglichkeit. Wir müssen aber eigentlich nur eine Methode austauschen...

Ich habe System.Reflection.Emit.MethodRental.SwapMethodBody gefunden, allerdings ist die Methode recht schlecht dokumentiert und sie funktioniert auch nur wenn man eine Klasse dynamisch zusammenbaut.

Gibt es irgendeine andere Möglichkeit, einen Methodenkörper zur Laufzeit durch einen anderen auszutauschen?

Viele Grüße,
Simon

D
500 Beiträge seit 2007
vor 15 Jahren

Wir verwenden hier in einer Firma eine Komponente, die wir an einer bestimmten Stelle erweitern wollen.

Heißt das, dass diese Komponente nicht von Euch kommt? Für mich hört sich Deine Idee ein wenig gefährlich an, da schnell den Überblick verlieren kann, wo eine Methode ausgetauscht wurde. Kannst Du nicht eventuell, falls die Schnittstelle, die Ihr verwendet nicht einfach dekorieren (Decorator Pattern)? Gibt es denn dazu ein Interface?

Gruß, DaMoe

S
SimonKnight6600 Themenstarter:in
709 Beiträge seit 2005
vor 15 Jahren

Hallo DaMoe80!

Die Komponente ist nicht von uns.

Für mich hört sich Deine Idee ein wenig gefährlich an, da schnell den Überblick verlieren kann, wo eine Methode ausgetauscht wurde

Soweit ich weiß ist das die einzige Möglichkeit. Und es ist nur eine Methode, da dürfte das kein Problem sein.

die Ihr verwendet nicht einfach dekorieren (Decorator Pattern

Nein, das ist leider nicht möglich 😦. Wir müssen die private Methode austauschen.

Viele Grüße,
Simon

6.862 Beiträge seit 2003
vor 15 Jahren

Wenns net unbedingt zur Laufzeit sein soll (oder vielleicht gehts auch da, weiß net genau), dann ist Cecil viellicht was für dich.

Baka wa shinanakya naoranai.

Mein XING Profil.

S
SimonKnight6600 Themenstarter:in
709 Beiträge seit 2005
vor 15 Jahren

Hallo talla!

Es muss leider ungebedingt zur Laufzeit sein.

Viele Grüße,
Simon

F
10.010 Beiträge seit 2004
vor 15 Jahren

Warum?

Erklär mal lieber was es ergeben soll, nicht wie ihr meint es machen zu wollen.

3.971 Beiträge seit 2006
vor 15 Jahren

Funktionen zur Laufzeit tauschen gibt und nennt sich delegaten. Die Anwendung muss dafür aber konzipiert sein.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

630 Beiträge seit 2007
vor 15 Jahren

Hallo SimonKnight6600,

so wie ich sehe ist dein Problem mit der SwapMethodBody-Methode das du keinen Token für die zu modifizierende Methode bekommst. Du kannst an den Token gelangen in dem du die MethodInfo der Methode wiederrum per Reflection untersuchst. puh

Das MethodInfo Objekt hat ein nicht öffentliche Eigenschaft "MethodToken". Wenn du diese hast brauchst du nur noch einen IntPtr auf ein Byte-Array welches den ILCode enthält. Das Array mit dem Code bekommst du über GetMethodBody().GetILAsByteArray(). (Von der neuen Methode)

Gruss
tscherno

To understand recursion you must first understand recursion

http://www.ilja-neumann.com
C# Gruppe bei last.fm

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo SimonKnight6600,

ich kann auch nicht ganz verstehen, warum die Methode unbedingt zur Laufzeit auszutauschen ist. Ist es nicht "besser", wenn man die bestehende Komponente nimmt, und in dieser dann die private Methode austauscht?

Ich würde da direkt über den IL Code gehen, und anstatt austauschen würde ich eine Art Umleitung vorschlagen, so dass eine neue Methode (die Deine) mit eingebaut wird, und überall wo auf die originale Methode verwiesen wird einfach auf Deine neue zu verweisen. Da es eine private Methode ist, hat sie auch einen begrenzten Gültigkeitsbereich, wo man sicher gehen kann, dass auch alle aufrufende Stellen gefunden werden kann.

Auf den Zielrechnern kann man dann die originale mit der veränderten Komponente austauschen, und fertig.

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
SimonKnight6600 Themenstarter:in
709 Beiträge seit 2005
vor 15 Jahren

Hallo tscherno!

Danke für deine Tipps. Auf diesem Weg konnte ich die Methode aufrufen, allerdings scheint das nicht bei bereits erstellten Typen (die nicht dynamisch angelegt werden) zu funktionieren:

Type t = typeof(TestClass);

MethodInfo methodToSwap = t.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
MemberInfo mb = (MemberInfo)methodToSwap;
PropertyInfo[] infos = methodToSwap.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );

int token = mb.MetadataToken;

// So bin ich nicht an die Property rangekommen, darum hab ichs mit dem MemberInfo Cast oben probiert. Daran liegts aber nicht!
// int token = Convert.ToInt32(mb.GetProperty("MetadataToken", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(mb, null));

byte[] ilCode = this.GetType().GetMethod("NewMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetMethodBody().GetILAsByteArray();

GCHandle handle = GCHandle.Alloc(ilCode, GCHandleType.Pinned);
IntPtr pointer = handle.AddrOfPinnedObject();

MethodRental.SwapMethodBody(t, token, pointer, ilCode.Length, 0);

handle.Free();

t.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance).Invoke( null, new object[]{});

Die MethodRental.SwapMethodBody-Methode kann nur aufgerufen werden, um den Methodentext in einem dynamischen Modul auszulagern.

Hallo norman_timo!

Die Assembly ist wie gesagt eine Drittkomponente und Änderungen daran sind nicht erlaubt.

Viele Grüße,
Simon

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo SimonKnight6600,

Die Assembly ist wie gesagt eine Drittkomponente und Änderungen daran sind nicht erlaubt.

Ob man die Änderungen nun im Arbeitsspeicher macht, oder direkt in der Datei, das spielt rechtlich gesehen keinen Unterschied. Einziger Vorteil beim "Ändern im Arbeitsspeicher" wäre die Nachweisbarkeit, die dadurch natürlich erheblich erschwert werden würde.

Aber wie gesagt ein Ändern ist ein Ändern, und da ist es gleich, ob in der Datei oder im Speicher...

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
SimonKnight6600 Themenstarter:in
709 Beiträge seit 2005
vor 15 Jahren

Hallo norman_timo!

Wir werden uns mal mit dem Hersteller von der Komponente in Verbindung setzen, ob es nicht eine andere Lösung gibt. (So dass wir das gewünschte ohne die Methode erreichen oder der Hersteller die Klasse ändert)

Vielen Dank,
Simon