Frage

Ich habe vor kurzem bei Reflection.Emit gesucht. Ich schrieb ein einfaches Programm, das eine Dynamic des einfachen Anrufe ein anderes Verfahren mit den gleichen Parametern

erzeugt
class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Test();
    }

    public delegate void TestHandler(int a, int b, int c, int d, int e, int f);

    public void Test()
    {
        DynamicMethod method = new DynamicMethod(string.Empty, typeof(void), new[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32) }, typeof(Program));


        MethodInfo method1 = typeof(Program).GetMethod("Question",BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,null,new Type[]{typeof(Int32),typeof(Int32),typeof(Int32),typeof(Int32),typeof(Int32),typeof(Int32)},null);
        MethodInfo method2 = typeof(MethodBase).GetMethod("GetCurrentMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
        MethodInfo method3 = typeof(Console).GetMethod("WriteLine", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Object) }, null);

        ILGenerator gen = method.GetILGenerator();

        gen.Emit(OpCodes.Nop);
        gen.Emit(OpCodes.Ldarg_S, 0);
        gen.Emit(OpCodes.Ldarg_S, 1);
        gen.Emit(OpCodes.Ldarg_S, 2);
        gen.Emit(OpCodes.Ldarg_S, 3);
        gen.Emit(OpCodes.Ldarg_S, 4);
        gen.Emit(OpCodes.Ldarg_S, 5);
        gen.Emit(OpCodes.Ldarg_S, 6);
        gen.Emit(OpCodes.Call, method1);
        gen.Emit(OpCodes.Nop);
        gen.Emit(OpCodes.Call, method2);
        gen.Emit(OpCodes.Call, method3);
        gen.Emit(OpCodes.Nop);
        gen.Emit(OpCodes.Ret);

        TestHandler handler = method.CreateDelegate(typeof(TestHandler)) as TestHandler;
        handler(1, 2, 3, 4, 5, 6);
    }

    public void Question(int a, int b, int c, int d, int e, int f)
    {
        Console.WriteLine("{0},{1},{2},{3},{4},{5}", a, b, c, d, e, f);
    }
}

Wenn ich dieses Beispiel auszuführen es ich es ausgeben 1,2,3,4,5,6 jedoch erwarten würde, gibt er 2,3,4,5,6,1

Ich bin mir nicht sicher, warum ... Wenn euch von jedem guten Ressourcen kennen Reflection.Emit für die Nutzung könnten Sie mir in dieser Richtung. Ich habe mit dem Emit AddIn mit Reflektor.

Prost

Rohan

War es hilfreich?

Lösung

Das Problem, das Sie ist, dass Sie eine dynamische Methode aufgerufen wird, nicht statisch. Ihre generierte Methode hat keinen Bezug auf die die Instanz der Programmklasse.

Beachten Sie auch, Sie drängen 7 Parameter auf den Stapel für eine 6-Parameter-Methode. Der erste Parameter sollte ein Verweis auf das Objekt sein, die Methode berufen sich auf.

Das seltsame Verhalten, das Sie aufgrund könnte es sein, sehen nicht ein Parameter des Index 6 ist und es um zurück zum Anfang des Parameters Array gewickelt wird.

Siehe. "Gewusst wie: Definieren und Ausführen Dynamische Methoden" in der VS-Hilfe

Sie können es durch die Annahme eines Objektparameter in Ihrem Methodenaufruf, oder macht es statisch bekommen arbeiten:

public delegate void TestHandler (Objektinstanz, int a, b int, int c, d int, int e, f int);

public void Test()
{
    DynamicMethod method = new DynamicMethod(string.Empty, typeof(void), new[] { typeof(object), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32) }, typeof(Program));


    MethodInfo method1 = typeof(Program).GetMethod("Question", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32) }, null);
    MethodInfo method2 = typeof(MethodBase).GetMethod("GetCurrentMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
    MethodInfo method3 = typeof(Console).GetMethod("WriteLine", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Object) }, null);

    ILGenerator gen = method.GetILGenerator();

    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ldarg_S, 0);
    gen.Emit(OpCodes.Ldarg_S, 1);
    gen.Emit(OpCodes.Ldarg_S, 2);
    gen.Emit(OpCodes.Ldarg_S, 3);
    gen.Emit(OpCodes.Ldarg_S, 4);
    gen.Emit(OpCodes.Ldarg_S, 5);
    gen.Emit(OpCodes.Ldarg_S, 6);
    gen.Emit(OpCodes.Call, method1);
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Call, method2);
    gen.Emit(OpCodes.Call, method3);
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ret);

    TestHandler handler = method.CreateDelegate(typeof(TestHandler)) as TestHandler;
    handler(this, 1, 2, 3, 4, 5, 6);
}

public void Question(int a, int b, int c, int d, int e, int f)
{
    Console.WriteLine("{0},{1},{2},{3},{4},{5}", a, b, c, d, e, f);
}

Andere Tipps

Um es Ihnen arbeiten sollte

  1. machen Question eine static Methode
  2. Kommentar gen.Emit(OpCodes.Ldarg_S,6);
  3. ändern MethodInfo method1 = ... entsprechend

Ein „Geruch“ ist, dass auf der Question Methode in Debug Stoppen Sie die this Referenz nicht auswerten können. Und sollte dies nicht für eine Instanz Methode sein ...; -)

Edit: Ops. Ich habe gerade die Antwort von Robert Wagner gesehen, die viel besser ist erklärt als meine. Bereit, meinen Beitrag zu stornieren, wenn nötig ...: -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top