Một gợi ý cho giải pháp có thể sử dụng lớp MethodBuilder. Sử dụng nó, bạn có thể tạo ra một phương thức tại thời gian chạy phù hợp với ủy nhiệm EventInfo mong đợi.
Ví dụ dựa vào nó (Nhiều tối ưu hóa có thể được thực hiện nhưng nó hoạt động cho hầu hết các trường hợp):
namespace AutoEventListener
{
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
public class EventExample
{
public static event EventHandler MyEvent;
public void Test()
{
bool called;
var eventInfo = GetType().GetEvent("MyEvent");
EventFireNotifier.GenerateHandlerNorifier(eventInfo,
callbackEventInfo =>
{
called = true;
});
MyEvent(null, null);;
}
}
public class EventFireNotifier
{
static private readonly Dictionary<int, EventInfo> eventsMap = new Dictionary<int, EventInfo>();
static private readonly Dictionary<int, Action<EventInfo>> actionsMap = new Dictionary<int, Action<EventInfo>>();
static private int lastIndexUsed;
public static MethodInfo GenerateHandlerNorifier(EventInfo eventInfo, Action<EventInfo> action)
{
MethodInfo method = eventInfo.EventHandlerType.GetMethod("Invoke");
AppDomain myDomain = AppDomain.CurrentDomain;
var asmName = new AssemblyName(){Name = "HandlersDynamicAssembly"};
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder myModule = myAsmBuilder.DefineDynamicModule("DynamicHandlersModule");
TypeBuilder typeBuilder = myModule.DefineType("EventHandlersContainer", TypeAttributes.Public);
var eventIndex = ++lastIndexUsed;
eventsMap.Add(eventIndex, eventInfo);
actionsMap.Add(eventIndex, action);
var handlerName = "HandlerNotifierMethod" + eventIndex;
var parameterTypes = method.GetParameters().Select(info => info.ParameterType).ToArray();
AddMethodDynamically(typeBuilder, handlerName, parameterTypes, method.ReturnType, eventIndex);
Type type = typeBuilder.CreateType();
MethodInfo notifier = type.GetMethod(handlerName);
var handlerDelegate = Delegate.CreateDelegate(eventInfo.EventHandlerType, notifier);
eventInfo.AddEventHandler(null, handlerDelegate);
return notifier;
}
public static void AddMethodDynamically(TypeBuilder myTypeBld, string mthdName, Type[] mthdParams, Type returnType, int eventIndex)
{
MethodBuilder myMthdBld = myTypeBld.DefineMethod(
mthdName,
MethodAttributes.Public |
MethodAttributes.Static,
returnType,
mthdParams);
ILGenerator generator = myMthdBld.GetILGenerator();
generator.Emit(OpCodes.Ldc_I4, eventIndex);
generator.EmitCall(OpCodes.Call, typeof(EventFireNotifier).GetMethod("Notifier"), null);
generator.Emit(OpCodes.Ret);
}
public static void Notifier(int eventIndex)
{
var eventInfo = eventsMap[eventIndex];
actionsMap[eventIndex].DynamicInvoke(eventInfo);
}
}
}
Lớp EventFireNotifier đăng ký cho EventInfo một Action mà được gọi khi sự kiện này là Bị sa thải.
Tôi hy vọng điều đó sẽ hữu ích.
Phương pháp này xuất hiện để tạo một dll cho mọi phương thức bạn tạo, có thể không làm chậm nó xuống một chút? – Kazar
Tôi nghĩ rằng phần chậm là tạo ra các phương pháp (sử dụng phản ánh) nhưng một khi nó được biên dịch tôi nghĩ rằng nó cần phải có hiệu suất tốt (nhưng tôi không bao giờ làm nó vì vậy tôi không thể chắc chắn ...). – Elisha
Điều đó trông giống như mã tốt (mặc dù nó đang sử dụng var, mà tôi không thể), tuy nhiên tôi đã tìm thấy cách giải quyết đơn giản hơn cho vấn đề của mình, bằng cách yêu cầu mã khởi tạo cấp cao nhất để cung cấp các đại biểu cho từng loại trình xử lý sự kiện. – Kazar