我有以下概念证明类:
private class SourceMock
{
public event PropertyChangedEventHandler TestEvent;
public void Raise()
{
if (this.TestEvent != null)
{
this.TestEvent(this, new PropertyChangedEventArgs("S"));
}
}
}
private class HandlerMock
{
public HandlerMock()
{
}
public void PropertyHandler(object sender, PropertyChangedEventArgs e)
{
}
}
然后,如果我执行以下操作,则可以:
SourceMock sourceMock = new SourceMock();
HandlerMock handler = new HandlerMock();
sourceMock.GetType().GetEvent("TestEvent").AddEventHandler(sourceMock, new PropertyChangedEventHandler(handler1.PropertyHandler));
但如果执行以下操作则不起作用:
SourceMock sourceMock = new SourceMock();
HandlerMock handler = new HandlerMock();
sourceMock.GetType().GetEvent("TestEvent").AddEventHandler(sourceMock, new EventHandler<PropertyChangedEventArgs>(handler1.PropertyHandler));
因为我得到以下异常:
System.ArgumentException:类型的对象 'System.EventHandler`1 [System.ComponentModel.PropertyChangedEventArgs]' 无法转换为类型 'System.ComponentModel.PropertyChangedEventHandler'。
我希望有一个处理事件的泛型类,我不能使用委托作为泛型类型我必须使用EventArgs,它强加给我第二种语法(非工作的)。
关于如何克服这个问题的任何想法?
编辑:这就是我想要实现的目标
我需要一个类来拦截事件并在提升之前做事(比如计算它们,过滤它们,重新排序它们等)。客户不会注册活动,但会要求此课程将其注册到活动中。我认为的签名如下:
public class EventHandlerService<T> where T : EventArgs
{
public void Register(object eventSource, string eventName, EventHandler<T> handler)
}
当事件发生时,服务将根据内部算法调用所有注册的处理程序。
在内部,它正在使用EventInfo类,它不能使用不是从EventHandler派生的EventHandler,因此这个问题。
答案 0 :(得分:2)
您可以看到,从EventHandler
/ EventHandler<T>
继承的事件的委托类型不是必需的。所以,这里的仿制药可能是多余的:
public class EventHandlerService
{
/// <example>
/// Use this overload, when delegate type for the event isn't inherited from EventHandler/EventHandler{T}.
/// <code>
/// service.Register(someObj, "SomeEvent", new PropertyChangedHandler(TheHandler));
/// </code>
/// </example>
public void Register(object eventSource, string eventName, Delegate handler)
{
// do the work here
}
/// <example>
/// Use this overload, when delegate type for the event is inherited from EventHandler{T}.
/// <code>
/// service.Register<FooEventArgs>(someObj, "SomeEvent", TheHandler);
/// </code>
/// </example>
public void Register<T>(object eventSource, string eventName, EventHandler<T> handler)
where T : EventArgs
{
Register(eventSource, eventName, handler);
}
/// <example>
/// Use this overload, when delegate type for the event is inherited from EventHandler.
/// <code>
/// service.Register(someObj, "SomeEvent", TheHandler);
/// </code>
/// </example>
public void Register(object eventSource, string eventName, EventHandler handler)
{
// we need cast here to help compiler to find desired overload
Register(eventSource, eventName, (Delegate)handler);
}
}
问题的特殊问题可以通过这种方式解决:
var eventInfo = sourceMock.GetType().GetEvent("TestEvent");
eventInfo.AddEventHandler(sourceMock, Delegate.CreateDelegate(eventInfo.EventHandlerType, handler, "PropertyHandler"));
但看起来你不需要解决它 - 只需删除泛型。