Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[gelöst] Zielmethode eines Call-Befehls auf CIL-Ebene ermitteln
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

Themenstarter:

[gelöst] Zielmethode eines Call-Befehls auf CIL-Ebene ermitteln

beantworten | zitieren | melden

Hallo,

ich spiele grad etwas mit dem Reflection.Emit-Namespace. Mein ziel ist eine bereits existierende Methode komplett nachzubauen.

Dazu hole ich mir den CIL-Code einer existierenden Methode mit GetType() GetMethod(...) GetMethodBody() GetILAsByteArray() und parse ihn zurück in eine Abfolge von OpCodes & passenden Operanden. Aus diesen baue ich dann mit ILGenerator und dem Emit(...) eine neue DynamicMethod, die ich dann aufrufe und hoffe, dass genau das selbe passiert, wie bei der Ausgangsmethode =).

Für eine Methode wie


static int foo(int x) {return x*4 +2;}
klappt das auch super aber für eine Methode wie


static int foo(int x) {return bar(x);}
klappt das nicht.
Anscheinend hakt das mit dem Call-Befehl Ein-/Auslesen irgendwie.

Folgende Beobachtungen habe ich gemacht:
  1. Der Operand des Call-Befehls aus der Ausgangsmethode ist eine Zahl und entspricht dem MethodInfo.MetadataToken der bar-Methode.
  2. Wenn ich denn Call Befehl per Hand emittiere, also mit

    Emit(OpCodes.Call, barMethodInfo);
    dann klappt es auch.

Nur ein

Emit(OpCodes.Call, barMethodInfo.MetadataToken);
klappt nicht ! (Aber aus dem Byte-Code bekomme ich nur das MetadataToken ausgelesen)

Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen? Bzw. irgendwie anders das zum Laufen zu bekommen?

Ich hoffe, ich konnte mein Anliegen rüberbringen, falls nicht: nachfragen

beste Grüße
zommi

PS: Mit Mono.Cecil geht das vielleicht irgendwie. Aber ich wollte es schon gern mit dem Standard-Framework versuchen.
PS2: Wenn ich auch mal in den emittierten CIL-Code blicken könnte, wäre das auch schön. Aber ein GetILAsByteArray() klappt bei einer DynamicMethod bringt immer nen Fehler.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von zommi am .
private Nachricht | Beiträge des Benutzers
dN!3L
myCSharp.de - Experte

Avatar #avatar-2985.png


Dabei seit:
Beiträge: 2.891

beantworten | zitieren | melden

Hallo zommi,
Zitat von zommi
Mein ziel ist eine bereits existierende Methode komplett nachzubauen.
Also wenn ich dich richtig verstehe, willst nicht du manuell eine Methode nachbauen, sondern ein Programm soll dynamisch beliebige Methoden nachbauen(?)
Zitat von zommi
Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen
Hast du mal MethodBase.GetMethodFromHandle (MethodInfo ist eine Spezialisierung von MethodBase) ausprobiert?

Gruß,
dN!3L
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dN!3L am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo zommi,
Zitat
Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen? Bzw. irgendwie anders das zum Laufen zu bekommen?
leider kann ich nur sehr diffus antworten: Ob man über das MetadataToken ran kommt, weiß ich nicht, aber rankommen muss man irgendwie. Der Reflector schafft es ja auch.

herbivore
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hi, danke erstmal für die Antworten,

@dN!3L,
über die Methode bin ich auch schon gestolpert, klappt aber auch nicht
GetMethodFromHandle braucht eben ein RunTimeMethodHandle und kein int32.
Außerdem ist

myMethodInfo.MethodHandle.Value != myMethodInfo.MetadataToken

@herbivore
jaja. gehen muss es :-)
Und prinzipiell müsste es ja auch gehen, wenn ich die komplette Assembly + alle referenzierten durchgehe, dort alle Typen und darin alle Methoden; mir von denen die MetadataToken hole und vergleiche. Aber das ist mir etwas zu viel BruteForce-Suche ;-)
(mhh.. wobei ich das natürlich einmal initial machen könnte und dann n Dictionary vorhalten...mhh...)

@dN!3l, (Klappe, die zweite)
Zitat
Also wenn ich dich richtig verstehe, willst du nicht manuell eine Methode nachbauen, sondern ein Programm soll dynamisch beliebige Methoden nachbauen(?)
Genau Also das simple Nachbauen ist die erste Stufe. Ein späteres Modifizieren ist die zweite. (Und insgesamt einer kleiner Schritt zu einem CIL-CIL-Optimierer)

viele grüße
zommi
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von zommi am .
private Nachricht | Beiträge des Benutzers
dN!3L
myCSharp.de - Experte

Avatar #avatar-2985.png


Dabei seit:
Beiträge: 2.891

beantworten | zitieren | melden

Hi zommi,

dann nimm Module.ResolveMethod. (Gibt auch noch andere Resolve*-Member von Module).


MethodInfo methodInfo = typeof(object).GetMethod("ToString");
MethodBase methodBase = methodInfo.Module.ResolveMethod(methodInfo.MetadataToken);
if (methodInfo==methodBase)
	Console.WriteLine("Yeehaa!");

Zitat von zommi
Und insgesamt einer kleiner Schritt zu einem CIL-CIL-Optimierer
Naja, Phoenix wurde ja für sowas entworfen. Aber mach's lieber selbst, mit Phoenix zu arbeiten ist das letzte...


Gruß,
dN!3L
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dN!3L am .
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Zitat von dN!3L
Yeehaa
Du sagst es
Diese Methode schickt der Himmel !

Danke
beste Grüße
zommi
private Nachricht | Beiträge des Benutzers