通过reflection为任何事件类型订阅操作

考虑:

someControl.Click += delegate { Foo(); }; 

事件的论点是无关紧要的,我不需要它们,我对它们不感兴趣。 我只想让Foo()被调用。 通过reflection没有明显的方法来做同样的事情。

我想将上述内容翻译成类似的内容

 void Foo() { /* launch missiles etc */ } void Bar(object obj, EventInfo info) { Action callFoo = Foo; info.AddEventHandler(obj, callFoo); } 

此外,我不想假设传递给Bar的对象类型严格遵守使用事件的EventHander(TArgs)签名的指导原则。 简单地说,我正在寻找一种方法来将Action订阅到任何处理程序类型; 简而言之,一种将Action委托转换为预期处理程序类型的委托的方法。

 static void AddEventHandler(EventInfo eventInfo, object item, Action action) { var parameters = eventInfo.EventHandlerType .GetMethod("Invoke") .GetParameters() .Select(parameter => Expression.Parameter(parameter.ParameterType)) .ToArray(); var handler = Expression.Lambda( eventInfo.EventHandlerType, Expression.Call(Expression.Constant(action), "Invoke", Type.EmptyTypes), parameters ) .Compile(); eventInfo.AddEventHandler(item, handler); } static void AddEventHandler(EventInfo eventInfo, object item, Action action) { var parameters = eventInfo.EventHandlerType .GetMethod("Invoke") .GetParameters() .Select(parameter => Expression.Parameter(parameter.ParameterType)) .ToArray(); var invoke = action.GetType().GetMethod("Invoke"); var handler = Expression.Lambda( eventInfo.EventHandlerType, Expression.Call(Expression.Constant(action), invoke, parameters[0], parameters[1]), parameters ) .Compile(); eventInfo.AddEventHandler(item, handler); } 

用法:

  Action action = () => BM_21_Grad.LaunchMissle(); foreach (var eventInfo in form.GetType().GetEvents()) { AddEventHandler(eventInfo, form, action); } 

这个怎么样?

 void Bar(object obj, EventInfo info) { var parameters = info.EventHandlerType.GetMethod("Invoke").GetParameters() .Select(p => Expression.Parameter(p.ParameterType)); var handler = Expression.Lambda( info.EventHandlerType, Expression.Call( Expression.Constant(obj), // obj is the instance on which Foo() "Foo", // will be called null ), parameters ); info.AddEventHandler(obj, handler.Compile()); }