Về cơ bản, tôi chấp nhận tên sự kiện dưới dạng chuỗi, để có được EventInfo
. Sau đó, tôi khám phá loại trình xử lý sự kiện và loại đối số sự kiện bằng cách sử dụng sự phản chiếu, tạo một đại biểu mới thuộc loại đó (myEventHandler
) và kết hợp nó với sự kiện. Khi bao giờ myEventHandler
được gọi, tôi cần phải downcast và truyền các đối số cho trình xử lý.IL Phát ra một cuộc gọi đại diện?
Mã của tôi như sau. Trình xử lý 'cần phải được gọi thông qua myEventHandler
, khi bao giờ' d 'được gọi. Tôi cần phải có một số mã emit Reflection có nơi tôi đặt ???. Có suy nghĩ gì không?
EventHandler handler = delegate(object sender, EventArgs eventArgs)
{
//something will happen here
};
Type[] typeArgs = { typeof(object), derivedEventArgsType };
DynamicMethod myEventHandler = new DynamicMethod("", typeof(void), typeArgs);
var ilgen = myEventHandler.GetILGenerator();
//What should be the IL code here to
//cast derviedEventArgs to EventArgs and
//invoke the 'handler' above??????
ilgen.Emit(OpCodes.Pop);
ilgen.Emit(OpCodes.Ret);
Delegate d = dynamic.CreateDelegate(derviedEventHandlerType);
//addMethod is the add MethodInfo for an Event
addMethod.Invoke(target, new object[] { d });
Chỉnh sửa: Dựa trên quan sát qua Reflector.
Các phản xạ tạo ra mã cho một kịch bản tự mã hóa là
.method public hidebysig instance void <Main>b__1(object sender, class ConsoleApplication2.MyEventArgs e) cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldfld class [mscorlib]System.EventHandler ConsoleApplication2.Program/<>c__DisplayClass3::handler
L_0007: ldarg.1
L_0008: ldarg.2
L_0009: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, class [mscorlib]System.EventArgs)
L_000e: nop
L_000f: ret
}
Và đây là những gì tôi đã cố gắng dựa trên đó.
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld,eh.GetType().GetField("handler"));
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Ldarg_2);
ilgen.EmitCall(OpCodes.Callvirt,eh.handler.Method,
new Type[]{ typeof(object), typeof(EventArgs) });
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ret);
Nhưng điều này đang gây ra một lỗi thời gian chạy:
'Calling convention must be varargs'
Có lẽ tôi là thiếu một cái gì đó, cần phải có một cái nhìn tốt hơn vào IL.
Bí quyết ở đây luôn đơn giản là viết mã bạn muốn trong C# và sử dụng bộ phản xạ/ILDASM để xem IL. Tôi sẽ đoán một sự kết hợp của ld, castclass, và callvirt –
Yep đồng ý. Tôi sẽ đi theo con đường đó, nhưng nghĩ rằng bất kỳ Reflection nào phát ra Ninjas trong SO có thể nhanh chóng chỉ ra điều này – amazedsaint
Nhìn lại - nơi nào "handler" cư trú? liên quan đến args? Tôi nghĩ nó sẽ là một nỗi đau khi đưa hai người lại gần nhau. Có vẻ như phiên bản C# sử dụng một lớp chụp, nhưng phương pháp động của bạn ở phút là tĩnh, vì vậy không nơi nào để xô bất kỳ trạng thái nào ... –