我知道可用于将处理程序附加到事件的EventInfo.AddEventHandler(...)
方法。但是,如果我甚至无法定义事件处理程序的正确签名,应该怎么做,因为我甚至没有引用处理程序所期望的事件args?
我将用正确的代码解释问题。
//当我在我的解决方案中提供一切可用的场景时,Zero Reflection Scenario。
internal class SendCommentsManager
{
public void Customize(IRFQWindowManager rfqWindowManager)
{
rfqWindowManager.SendComment += HandleRfqSendComment;
}
private void HandleRfqSendComment(object sender, SendCommentEventArgs args)
{
args.Cancel = true;
}
}
现在,我希望通过使用反射来实现相同的目标。我已经能够找出大部分内容但是当我将一个委托附加到事件时(使用AddEventHandler
)它会引发"Error binding to target method."
异常。
我理解这个异常背后的原因,将错误的委托附加到事件中。但必须有一些方法来实现这一目标。
internal class SendCommentsManagerUsingReflection
{
public void Customize(IRFQWindowManager rfqWindowManager)
{
EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
eventInfo.AddEventHandler(rfqWindowManager,
Delegate.CreateDelegate(eventInfo.EventHandlerType, this, "HandleRfqSendComment"));
//<<<<<<<<<<ABOVE LINE IS WHERE I AM GOING WRONG>>>>>>>>>>>>>>
}
private void HandleRfqSendComment(object sender, object args)
{
Type sendCommentArgsType = args.GetType();
PropertyInfo cancelProperty = sendCommentArgsType.GetProperty("Cancel");
cancelProperty.SetValue(args, true, null);
}
}
答案 0 :(得分:10)
我认为您的代码失败了,因为HandleRfqSendComment
是私有的。相反,您可以直接创建该方法的委托,而不将其名称传递给CreateDelegate
。然后,您需要使用以下方法将委托转换为所需类型:
public static Delegate ConvertDelegate(Delegate originalDelegate, Type targetDelegateType)
{
return Delegate.CreateDelegate(
targetDelegateType,
originalDelegate.Target,
originalDelegate.Method);
}
在您的代码中,您可以按如下方式使用此方法:
EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
Action<object, object> handler = HandleRfqSendComment;
Delegate convertedHandler = ConvertDelegate(handler, eventInfo.EventHandlerType);
eventInfo.AddEventHandler(rfqWindowManager, convertedHandler);
答案 1 :(得分:0)
这里已经很棒的答案的一个小补充。这是一个可用于订阅带有操作的事件的辅助类。
public static partial class ReactiveExtensions
{
public static EventHandler<TEvent> CreateGenericHandler<TEvent>(object target, MethodInfo method)
{
return (EventHandler<TEvent>)Delegate
.CreateDelegate(typeof(EventHandler<TEvent>),
target, method);
}
public static EventHandler CreateHandler(object target, MethodInfo method)
{
return (EventHandler)Delegate
.CreateDelegate(typeof(EventHandler),
target, method);
}
static void BindEventToAction(object target, EventInfo eventInfo, Delegate action)
{
MethodInfo method;
if (eventInfo.EventHandlerType.IsGenericType)
{
method = typeof(ReactiveExtensions)
.GetMethod(nameof(CreateGenericHandler))
.MakeGenericMethod(
eventInfo.EventHandlerType.GetGenericArguments());
}
else
{
method = typeof(ReactiveExtensions)
.GetMethod(nameof(CreateHandler));
}
Delegate @delegate = (Delegate)method.Invoke(null,
new object[] { action.Target, action.Method });
eventInfo.AddEventHandler(target, @delegate);
}
}
以下是有关如何使用它的示例:
public static partial class ReactiveExtensions
{
public static void Subscribe<T>(T source, string eventName)
{
EventInfo eventInfo = typeof(T).GetEvent(eventName);
Action<object, object> action = (s, e) =>
{
Console.WriteLine("Event Called");
};
BindEventToAction(source, eventInfo, action);
}
}