我有问题,test1生产"系统。argumentException:方法参数长度不匹配",而test2和test3则良好。我需要使用反射订阅事件,如果我使用简单的方法,一切都有效,但是当我进入lambdas时,它会停止按预期工作。
调试所有lambdas显示它们是" void<> m__0(int32(",这是事件的正确类型,与" EventInfo.eventhandhandlertype"相同。
为什么失败?也许,如何解决问题?
c#是否将更多参数添加到lambda创建的方法中,例如test1?
中::在此处完成代码:
public class A
{
public void Test1()
{
var str = "aa";
B.Subscribe(typeof(C), "myEvent", (int a) => { var any = str; }, null);
}
public void Test2()
{
B.Subscribe(typeof(C), "myEvent", (int a) => { var any = a; }, null);
}
public void Test3()
{
B.Subscribe<int>(typeof(C), "myEvent", callback, this);
}
public void callback(int a) { }
}
public static class B
{
public static void Subscribe<T>(Type type, string eventName, Action<T> callback, object target)
{
var eventInfo = type.GetEvent(eventName, BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, target, callback.Method);
eventInfo.AddEventHandler(null, handler);
}
}
public sealed class C
{
public static event Action<int> myEvent;
}
编辑:
显然是单声道错误。getInvocationList(([0]在上面的示例中将代表解决问题。
但要订阅事件会产生"系统。如果事件不是类型的操作,而是自定义代表:(如果类似" C"类,则会投掷,如果类似于上面的类,则可以通过(
(public sealed class C
{
public static event MyDel myEvent;
public delegate void MyDel(int a);
}
这是不同的问题吗?编辑#2,事件期望MyDel
类型,但获取操作INT32。我如何从Action<T>
转换为MyDel或更高的eventInfo.EventHandlerType
,因为我不知道可以发生哪种类型的事件。
实际上,经过进一步的调查,我注意到我的 target
不好。
对于类在类中定义的方法,类实例为目标是可以的。对于lambdas,我认为它是空的,至少它可以与null一起使用,只要它不干扰创建lambda的方法中定义的局部变量。
so Action 使用Delegate.CreateDelegate
中的callback.Target
具有属性 TARGET 解决了问题。
lambda的目标实际上包含对类实例的引用,以及它触摸的所有本地变量(调试器显示(。
奇怪的是,它在最新的.net上起作用,也许是单声道和.net之间的略有区别。