문제

EventConsumer라는 클래스가 있습니다. 이벤트는 이벤트 소비와 다음과 같이 oneventConsumed 메소드를 정의합니다.

public event EventHandler EventConsumed;

public virtual void OnEventConsumed(object sender, EventArgs e)
{
    if (EventConsumed != null)
        EventConsumed(this, e);
}

AT OneventConsumed 런타임에 속성을 추가해야하므로 System.Reflection.emit을 사용하여 서브 클래스를 생성합니다. 내가 원하는 것은 이것과 동등한 MSIL입니다.

public override void OnEventConsumed(object sender, EventArgs e)
{
    base.OnEventConsumed(sender, e);
}

내가 지금까지 가지고있는 것은 다음과 같습니다.

...

MethodInfo baseMethod = typeof(EventConsumer).GetMethod("OnEventConsumed");
MethodBuilder methodBuilder = typeBuilder.DefineMethod("OnEventConsumed",
                                                       baseMethod.Attributes,
                                                       baseMethod.CallingConvention,
                                                       typeof(void),
                                                       new Type[] {typeof(object),
                                                                   typeof(EventArgs)});

ILGenerator ilGenerator = methodBuilder.GetILGenerator();

// load the first two args onto the stack
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Ldarg_2);

// call the base method
ilGenerator.EmitCall(OpCodes.Callvirt, baseMethod, new Type[0] );

// return
ilGenerator.Emit(OpCodes.Ret);

...

유형을 생성하고 유형의 인스턴스를 만들고 OneventConsumed 함수를 호출하면 다음을 얻습니다.

Common Language Runtime detected an invalid program.

... 정확히 도움이되지 않습니다. 내가 뭘 잘못하고 있죠? 기본 클래스의 이벤트 핸들러를 호출하는 올바른 MSIL은 무엇입니까?

도움이 되었습니까?

해결책

다음은 샘플 앱의 IL입니다.


.method public hidebysig virtual instance void OnEventConsumed(object sender, class [mscorlib]System.EventArgs e) cil managed
    {
        .maxstack 8
        L_0000: nop 
        L_0001: ldarg.0 
        L_0002: ldarg.1 
        L_0003: ldarg.2 
        L_0004: call instance void SubclassSpike.BaseClass::OnEventConsumed(object, class [mscorlib]System.EventArgs)
        L_0009: nop 
        L_000a: ret 
    }

그래서 나는 당신이 ldarg.0을하지 않기 때문에 인스턴스를로드하지 않는 것 같습니다.

다른 팁

나는 실제로 정말 가까웠다 - 문제는 내가 '이'주장을로드하지 않았다는 것이었다. 그 섹션은 다음과 같이됩니다.

// load 'this' and the first two args onto the stack
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Ldarg_2);

// call the base method
ilGenerator.EmitCall(OpCodes.Call, baseMethod, new Type[0] );

// return
ilGenerator.Emit(OpCodes.Ret);

이제 잘 작동합니다.

사용

public virtual void OnEventConsumed(object sender, EventArgs e)
{
    if (EventConsumed != null)
        EventConsumed(this, e);
}

해야한다

public virtual void OnEventConsumed(EventArgs e)
{
    EventHandler handler = this.EventConsumed;
    if ( null != handler ) handler( this, e );
}

.

나는 당신은 a를 사용해야한다고 생각합니다 ilgenerator.emitcalli 그리고 당신은 반환 값 유형 (이 경우 null이라고 생각합니다)을 전달하고 인수 유형을 전달해야합니다.

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