문제

나는 최근에 반사를보고있다. 동일한 매개 변수로 다른 메소드를 호출하는 DynamicMethod를 생성하는 간단한 프로그램을 작성했습니다.

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);
    }
}

이 예제를 실행하면 1,2,3,4,5,6을 출력 할 것으로 예상하지만 2,3,4,5,6,1을 출력합니다.

왜 그런지 잘 모르겠습니다 ... 여러분이 반사를 사용하는 좋은 자원을 알고 있다면 그 방향으로 나를 가리킬 수 있습니다. 나는 Emit Addin과 함께 반사기를 사용하고 있습니다.

건배

로한

도움이 되었습니까?

해결책

당신이 가진 문제는 당신이 정적 방법이 아니라 동적 방법을 호출한다는 것입니다. 생성 된 메소드에는 프로그램 클래스의 인스턴스에 대한 참조가 없습니다.

또한 6 개의 매개 변수 메소드를 위해 7 개의 매개 변수를 스택에 푸시합니다. 첫 번째 매개 변수는 메소드를 호출하는 객체를 참조해야합니다.

당신이보고있는 이상한 동작은 인덱스 6의 매개 변수가 없기 때문에 매개 변수 배열의 시작으로 되돌아 가기 때문일 수 있습니다.

VS 도움말에서 "방법 : 동적 메소드를 정의하고 실행"을 참조하십시오.

메소드 호출에서 객체 매개 변수를 수락하거나 정적으로 만들어 작동 할 수 있습니다.

Public Delegate void testAndler (객체 인스턴스, 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(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);
}

다른 팁

그것을 작동 시키려면 당신이해야합니다

  1. 만들다 Questionstatic 방법
  2. 논평 gen.Emit(OpCodes.Ldarg_S,6);
  3. 수정하다 MethodInfo method1 = ... 따라서

하나의 "냄새"는 디버그에서 멈추는 것입니다. Question 방법을 평가할 수 없습니다 this 참조. 그리고 이것은 인스턴스 방법에 대한 것이어야합니다 ... ;-)

편집 : OPS. 나는 Robert Wagner의 답을 내 것보다 훨씬 더 잘 설명했습니다. 필요한 경우 내 게시물을 취소 할 준비가되었습니다 ... :-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top