好的-这可能有帮助;它生成IL来在委托类型之间切换,只要它们符合标准模式。它只在必要时添加castclass(因此,如果您要从
MouseEventArgs
对
EventArgs
这是不必要的,但在相反的方向上是必要的)。因为你显然是在思考,所以我没有使用泛型(这会使事情变得更困难)。
厚颜无耻的一点是,不要用
捕获
类,它假装该方法属于我要捕获的数据,并将状态用作
arg0
.我不能决定这是邪恶还是聪明,所以我会选择“克莱维尔”。
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Windows.Forms;
class Program {
static ParameterInfo[] VerifyStandardHandler(Type type) {
if (type == null) throw new ArgumentNullException("type");
if (!typeof(Delegate).IsAssignableFrom(type)) throw new InvalidOperationException();
MethodInfo sig = type.GetMethod("Invoke");
if (sig.ReturnType != typeof(void)) throw new InvalidOperationException();
ParameterInfo[] args = sig.GetParameters();
if (args.Length != 2 || args[0].ParameterType != typeof(object)) throw new InvalidOperationException();
if (!typeof(EventArgs).IsAssignableFrom(args[1].ParameterType)) throw new InvalidOperationException();
return args;
}
static int methodIndex;
static Delegate Wrap(Delegate value, Type type) {
ParameterInfo[] destArgs = VerifyStandardHandler(type);
if (value == null) return null; // trivial
if (value.GetType() == type) return value; // already OK
ParameterInfo[] sourceArgs = VerifyStandardHandler(value.GetType());
string name = "_wrap" + Interlocked.Increment(ref methodIndex);
Type[] paramTypes = new Type[destArgs.Length + 1];
paramTypes[0] = value.GetType();
for (int i = 0; i < destArgs.Length; i++) {
paramTypes[i + 1] = destArgs[i].ParameterType;
}
DynamicMethod dyn = new DynamicMethod(name, null, paramTypes);
MethodInfo invoker = paramTypes[0].GetMethod("Invoke");
ILGenerator il = dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
if (!sourceArgs[1].ParameterType.IsAssignableFrom(destArgs[1].ParameterType)) {
il.Emit(OpCodes.Castclass, sourceArgs[1].ParameterType);
}
il.Emit(OpCodes.Call, invoker);
il.Emit(OpCodes.Ret);
return dyn.CreateDelegate(type, value);
}
static void Main() {
EventHandler handler = delegate(object sender, EventArgs eventArgs) {
Console.WriteLine(eventArgs.GetType().Name);
};
MouseEventHandler wrapper = (MouseEventHandler)Wrap(handler, typeof(MouseEventHandler));
MouseEventArgs ma = new MouseEventArgs(MouseButtons.Left, 1, 1, 1, 1);
wrapper(new object(), ma);
EventHandler backAgain = (EventHandler)Wrap(wrapper, typeof(EventHandler));
backAgain(new object(), ma);
}
}
显然,您仍然需要使用常规方法生成事件的委托(
Delegate.CreateDelegate
但是你可以把它包装成
EventHandler
或者反过来。