Alle Parameter einer Methode als Array bekommen



  • Hi Leute,

    gibt es eine Möglichkeit die Werte, Namen und Typen aller Parameter die an eine Funktion übergeben wurden als Array zu bekommen?
    Hintergrund ist Logging.

    P.S. Wenn du denkst, ich suche nach dem params-Keyword, dann hast du meine Frage nicht verstanden 😉



  • Nein, weil Namen Schall und Rauch sind. Typen dagegen kannst du bekommen, Werte nicht.



  • Talla schrieb:

    Nein, weil Namen Schall und Rauch sind. Typen dagegen kannst du bekommen, Werte nicht.

    So wertlos sind die Namen nicht. Über Reflection kommt man an die Namen vieler Elemente... Das wichtigste sind die Werte. Die Namen und die Typen kann ich zur Not über Reflection herausfinden und dann zuordnen...
    Bist du dir sicher, dass man nicht an die Werte kommt?



  • dEUs schrieb:

    gibt es eine Möglichkeit die Werte, Namen und Typen aller Parameter die an eine Funktion übergeben wurden als Array zu bekommen? Hintergrund ist Logging.

    Allem vorweg: Ich verstehe nicht wirklich, was Du vorhast... Wenn Du mit Assemblies arbeitest, zu denen das Code verfügbar ist, verwende doch einfach Code-Generatoren um die Parameter zu loggen. Wenn das Code nicht vorliegt, scheint es ein klassischer Fall für die Verwendung von Debugging-Tools oder der Windows Debugging API zu sein. Aber ich will dennoch versuchen, einiges darüber zu sagen.

    Die Parameter könntest Du z.B. so kriegen:

    StackFrame stackFrame = new StackFrame(0, false);
    System.Reflection.ParameterInfo[] methodParameters = stackFrame.GetMethod().GetParameters();
    

    Keine große Sache. Die Geschichte um die Parameter-WERTE ist jedoch komplizierter. Meine kurze Antwort lautet: Das ist nicht möglich. Die lange Antwort ist: JAIN.

    Wenn Du C++ verwenden würdest, würde ich jetzt ohne weiter zu denken sagen: Verwende Assembler und hol dir einfach was Du brauchst vom Stapel. Das ist relativ einfach.

    Weil wir jetzt aber über C# sprechen, ist es nicht ganz so einfach (zumindest nicht für mich). Ich will das erklären.

    Wenn man sich das IL-Code vor dem Aufruf einer Funktion wie

    AddOne(int value);
    

    ansieht, dann sieht es etwa so aus:

    ldc.ip.s 0x16
    call instance void Project1.Form1::AddOne(int32)
    

    Also: Ein Int-Wert wird auf dem evalutation stack abgelegt, dann wird die Methode AddOne() aufgerufen. Sollte diese den Wert der Arguments brauchen, muss sie es so abrufen:

    ldarg.1
    

    Wenn die Methode AddOne() den Parameterwert nicht verwendet (tolle Programmierung!), wird dieser zwar auf dem Auswertungsstapel abgelegt, aber es gibt freilich keine IL-Anweisung im ganzen Methoden-Korpus, die auf diesen Wert Bezug nimmt.

    Wir haben möglicherweise keine Verwendung für alle Parameter in einer Funktion, möchten aber doch gerne die Werte der Argumente kennen, die auf den Stapel vor derm Aufruf unserer Methode abgelegt wurden (irgendwie Irrsinn, oder?).

    Was tun? IL-Code zur Laufzeit generieren? Aber das läuft doch in irgendeiner DynamicMethod ab und nicht in der Methode, die wir untersuchen wollen (ein ganz andere Stack). Lange Rede, kurzer Sinn. Bleibt nur eins: Code Injection. Wir müssen in jeder Prozedur, die wir untersuchen wollen das Code injizieren, das wir für den Zugriff auf die Parameter brauchen, z.B.

    ldarg.1
    

    .

    Wie können wir das tun? Mit Hilfe von Reflexil von Jb Evain (eine Anleitung unter: http://www.codeproject.com/KB/msil/reflexil.aspx). Klar bedeutet das eine Menge Arbeit, was besseres fällt mir aber z.Z. nicht ein.

    Also: Was nicht ist, kann noch werden. Entweder Du injizierst Code über einen Code-Generator oder über IL. Und solltest Du einen anderen Weg finden, vergess bitte nicht, dass ich dran interessiert bin!!! 😃



  • uiuiui *g*
    Ja, ich habe den Quellcode. Und ich bin eigentlich kein Fan von Code-Generatoren, nicht umsonst hat man in C# die Makros abgeschafft...
    Aber dann wird mir wohl nichts anderes übrigbleiben... 😞


Anmelden zum Antworten