Kaz*_*zar 5 .net c# events delegates
我有一个函数接收两个参数 - 一个对象,以及一个定义该对象上的事件的EventInfo结构.我需要阻止该函数,直到指定的事件触发.我遇到的问题是,当处理程序的类型可以是什么时,如何向指定的事件添加委托?请注意,我不关心那个结果事件调用的参数,我只需要抓住它引发的事实.
我已经尝试使用EventInfo.AddEventHandler添加一个非常通用的委托类型(EventHandler),但无济于事.我也尝试了相同的,但Activator用于创建EventInfo.EventHandlerType属性中指定类型的实例,但没有快乐.
或者,如果有人有办法做类似的,给定一个对象,以及该对象上的事件名称,那么这也可以.
我正在使用C#和.NET 2.0.
干杯
解决方案的提示可以使用MethodBuilder类。使用它,您可以在运行时生成适合 EventInfo 期望的委托的方法。
基于它的示例(可以进行许多优化,但它适用于大多数情况):
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
EventFireNotifier类为EventInfo注册一个在事件触发时调用的操作。
我希望它有帮助。
| 归档时间: |
|
| 查看次数: |
1388 次 |
| 最近记录: |