我有一个Windows Phone页面(MainPage),在代码隐藏中,我想动态添加一个事件处理程序 - 例如到MouseEnter事件。诀窍是,我希望这个事件处理程序将事件参数作为对象:
private void MyEventHandler(object sender, object args)
{
}
(原因是这是一个简化的例子)
这有效:
this.MouseEnter += MyEventHandler;
但是这会引发ArgumentException:
var handlerType = Type.GetType("System.EventHandler`1").
MakeGenericType(typeof(EventArgs));
this.GetType().GetEvent("Hold").AddEventHandler(
this, Delegate.CreateDelegate(handlerType, this, "MyEventHandler"));
异常的消息是: “无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明度不兼容。”如果我更改事件处理程序的签名,一切正常,但我希望将其保留为“对象”或“动态”。
如何使用AddEventHandler调用添加事件处理程序?
非常感谢任何帮助。
答案 0 :(得分:1)
看起来您需要求助于DynamicMethod和ILGenerator来生成与事件处理程序的签名匹配的方法。然后在DynamicMethod实现中调用一个具有签名void MyEventHandler(object,object)的全局事件处理程序。
public MainPage()
{
var handler = Create<MouseEventHandler>();
this.LayoutRoot.MouseMove += handler;
}
public static void MyEventHandler(object sender, object args)
{
Debug.WriteLine("MyEventHandler({0}, {1})", sender, args);
}
private TDelegate Create<TDelegate>()
{
// retrieve parameter types from delegate type
var delegateType = typeof(TDelegate);
var invoke = delegateType.GetMethod("Invoke");
var parameterTypes = (from p in invoke.GetParameters()
select p.ParameterType).ToArray();
// create dynamic event handler having TDelegate signature
var method = new DynamicMethod("", null, parameterTypes);
var myEventHandlerMethod = typeof(MainPage).GetMethod("MyEventHandler");
var generator = method.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Call, myEventHandlerMethod); // invoke my event handler
generator.Emit(OpCodes.Ret);
return (TDelegate)(object)method.CreateDelegate(delegateType);
}
答案 1 :(得分:0)
包装它的匿名方法应该可以解决这个问题: this.MouseEnter + =(s,e)=&gt;一个MyEventHandler(S,E);