我希望将事件传递给辅助函数。此函数将附加方法到事件。但是,我无法正确传递活动。我试过传递EventHandler<TEventArgs>
。它编译,但事件没有附加(但仍然添加;它似乎是事件处理程序的副本)。
例如,如果我有这个:
public event EventHandler<EventArgs> MyEvent;
辅助函数:
public static void MyHelperFunction<TEventArgs>(EventHandler<TEventArgs> eventToAttachTo)
{
eventToAttachTo += (sender, e) => { Console.WriteLine("Hello world"); };
}
来电者:
MyHelperFunction(MyEvent);
MyEvent(null, new EventArgs()); // Does nothing.
答案 0 :(得分:17)
这不起作用的原因是+ =当应用于委托时创建一个新委托,它是旧的和新的组合。它不会修改现有的委托。
为了使其工作,您必须通过引用传递委托。
public static void Helper(ref EventHandler<EventArgs> e)
{
e+= (x,y) => {};
}
这种方法在方法之外工作的原因是因为LHS仍然是实际的领域。所以+ =将创建一个新的委托并分配回成员字段。
答案 1 :(得分:3)
刚出现这个小帮手。如果是你自己创建的事件,你可以使用这样的包装器。您可以使用+ =运算符正常附加处理程序,但可以传递包装器,甚至可以从其他地方引发事件。
public class GenericEvent<T> where T:EventArgs
{
public event EventHandler<T> Source = delegate { };
public void Raise(object sender, T arg = default(T))
{
Source(sender, arg);
}
public void Raise(T arg = default(T))
{
Source(this, arg);
}
public void AddHandler(EventHandler<T> handler)
{
Source += handler;
}
public void RemoveHandler(EventHandler<T> handler)
{
Source -= handler;
}
public static GenericEvent<T> operator +(GenericEvent<T> genericEvent, EventHandler<T> handler)
{
genericEvent.AddHandler(handler);
return genericEvent;
}
}
创建如下事件:
public GenericEvent<EventArgs> MyEvent = new GenericEvent<EventArgs>();
附加处理程序:
MyEvent += (s,e) => {};
举起活动:
MyEvent.Raise();
答案 2 :(得分:2)
猜测:您是否尝试将其作为参考传递?
public static void MyHelperFunction<TEventArgs>(ref EventHandler<TEventArgs> eventToAttachTo)
MyHelperFunction(ref MyEvent);
答案 3 :(得分:2)
这不太好,但你可以使用反射来做到这一点。
public EventMonitor(object eventObject, string eventName)
{
_eventObject = eventObject;
_waitEvent = eventObject.GetType().GetEvent(eventName);
_handler = new EventHandler(SetEvent);
_waitEvent.AddEventHandler(eventObject, _handler);
}
其中eventObject是包含事件的对象,eventName是事件的名称。 SetEvent是你的事件处理程序。
我也有这样的处理方法:
public void Dispose()
{
_waitEvent.RemoveEventHandler(_eventObject, _handler);
}
答案 4 :(得分:1)
我有一个解决方案,我有两个接口。第一个接口具有绑定某些事件的方法,而另一个接口具有可以绑定到这些事件的事件方法。
第一个接口的bind方法将第二个接口作为参数,这样就可以将事件绑定到实现第二个接口的任何类的事件方法。
这是可以理解的,还是您更喜欢某些代码? :)
答案 5 :(得分:1)
许多人已经指出,将事件传递给方法要么不可能,要么不简单。
请澄清,但我怀疑您的预期用途如下:
void Register()
{
var super = new SuperHandler();
//not valid syntax:
super.HandleEvent(MyEvent1);
super.HandleEvent(MyEvent2);
super.HandleEvent(MyEvent3);
super.HandleEvent(MyEvent4);
}
您可以通过公开(或内部,如果您愿意)访问您的预期通用事件处理程序来实现此目的:
public static class GenericHandler
{
public static void HandleAnyEvent(object sender, EventArgs e)
{
//handle
}
}
public class SomeClass
{
void RegisterEvents()
{
var r = new EventRaiser();
r.ImportantThingHappened += GenericHandler.HandleAnyEvent;
}
}
在这个例子中,我的catch-all处理程序在一个静态类中,但你也可以使用非静态类。另外,我在你的例子中看到你使方法通用(TEventArgs)。因为所有EventHandler派生词(例如CancelEventHandler)都与基本的EventHandler匹配,所以您不需要涉及泛型(也不会有帮助)。
如果注册逻辑很复杂或者您必须将EventHandler保密,请考虑使用接口事件。这可能无法满足您减少代码量的预期目标,但它将允许您创建一个可以预测处理特定类型的所有事件的类。
interface IRaiseEvents
{
event EventHandler ConnectionCreated;
event EventHandler ConnectionLost;
}
public class SuperHandler
{
void RegisterEvents(IRaiseEvents raiser)
{
raiser.ConnectionCreated += (sender, args) => Console.WriteLine("Connected.");
raiser.ConnectionLost += (sender, args) => Console.WriteLine("Disconnected.");
}
}
答案 6 :(得分:1)
传递类似Action e = e =&gt;的内容myevent + = e; 并使用处理程序从方法调用?它具有使用.NET类的好处。