如何将事件传递给C#中的函数?
我希望将事件传递给助手函数。此函数将向事件附加一个方法。然而,我很难顺利通过这项赛事。我已尝试传递如何将事件传递给C#中的函数?,c#,delegates,C#,Delegates,我希望将事件传递给助手函数。此函数将向事件附加一个方法。然而,我很难顺利通过这项赛事。我已尝试传递EventHandler。它进行编译,但没有附加事件(但仍然添加了事件;似乎创建了事件处理程序的副本) 例如,如果我有: public event EventHandler<EventArgs> MyEvent; 猜猜看:你试过以裁判的身份传球吗 public static void MyHelperFunction<TEventArgs>(ref EventHandler
EventHandler
。它进行编译,但没有附加事件(但仍然添加了事件;似乎创建了事件处理程序的副本)
例如,如果我有:
public event EventHandler<EventArgs> MyEvent;
猜猜看:你试过以裁判的身份传球吗
public static void MyHelperFunction<TEventArgs>(ref EventHandler<TEventArgs> eventToAttachTo)
MyHelperFunction(ref MyEvent);
publicstaticvoidmyhelperfunction(refeventhandler eventToAttachTo)
MyHelperFunction(参考MyEvent);
这不起作用的原因是+=当应用于委托时,会创建一个新委托,该委托是新旧委托的组合。它不会修改现有委托
为了使其工作,您必须通过引用传递代理
public static void Helper(ref EventHandler<EventArgs> e)
{
e+= (x,y) => {};
}
publicstaticvoid助手(refeventhandler e)
{
e+=(x,y)=>{};
}
这在方法之外工作的原因是因为LHS仍然是实际字段。So+=将创建一个新的委托并分配回成员字段。我有一个解决方案,其中我有两个接口。第一个接口具有绑定某些事件的方法,而另一个接口具有可以绑定到这些事件的事件方法 第一个接口的绑定方法将第二个接口作为参数,这使得可以将事件绑定到实现第二个接口的任何类的事件方法
这是可以理解的,还是您更喜欢一些代码?:) 这不太好,但可以使用反射来实现
public EventMonitor(object eventObject, string eventName)
{
_eventObject = eventObject;
_waitEvent = eventObject.GetType().GetEvent(eventName);
_handler = new EventHandler(SetEvent);
_waitEvent.AddEventHandler(eventObject, _handler);
}
其中eventObject是包含事件的对象,eventName是事件的名称。
SetEvent是您的事件处理程序
我还有这样一个dispose方法:
public void Dispose()
{
_waitEvent.RemoveEventHandler(_eventObject, _handler);
}
正如许多人指出的,将事件传递给方法不是不可能,就是不简单
void Register()
{
var super = new SuperHandler();
//not valid syntax:
super.HandleEvent(MyEvent1);
super.HandleEvent(MyEvent2);
super.HandleEvent(MyEvent3);
super.HandleEvent(MyEvent4);
}
您可以通过公开(或在内部,如果愿意的话)访问预期的通用事件处理程序来实现这一点:
在本例中,我的catch-all处理程序位于静态类中,但您也可以使用非静态类。此外,我看到在您的示例中,您已经将方法设置为通用(TEventArgs)。因为所有EventHandler派生(如CancelEventHandler)都与基本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.");
}
}
刚刚想出了一个小帮手。如果是您自己创建的事件,您可以使用这样的包装器。您可以使用+=运算符正常地附加处理程序,但可以传递包装器,甚至从其他地方引发事件
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;
}
}
筹款活动:
MyEvent.Raise();
传递动作e=e=>myevent+=e;
和使用处理程序从方法调用?与.NET类一起使用有好处。很有趣。所以我猜+=会重新创建委托(比如e=e+func)。谢谢你的帮助!我花了几个小时试图调试我的代码(将其归咎于线程),而事实上事件并没有在应该触发的时候触发。@strager,当你遇到这种情况时,最好抛出Reflector。它将解开一些误导性的语法结构,并向您展示实际发生的情况。使用ref的问题:如果使用Helper(ref myClassInstance.MyEvent),我会出现以下错误:事件MyEvent只能出现在+=或-=(从类型MyClass中使用时除外)的左侧。我如何解决这个问题呢?请注意,我只是在单元测试中这样做(所以我想我可以使用内部测试),但是有一个干净的公共解决方案也很好。我也有同样的问题。你找到解决左侧错误的方法了吗?@Strager:你介意详细说明一下你是如何使用这个的吗?我发现这个问题很有趣,但我很难看到用例。@John Feminella,我正在创建一些帮助函数,其中一个同步等待事件。它们主要用于减少我的网络类(异步操作)中几个WaitFor方法(例如WaitForConnected)的代码重用。一个很好的简单类。为了使它更复杂,我建议使用订阅事件的事件列表。如果释放GenericEvent对象,它将取消订阅所有订阅的事件。这可能意味着GenericEvent实现IDisposable接口。你说得对。如果我必须解决这个问题,我现在可能会这么做四年前,当我对C#不太了解时,我问了这个问题。不过,感谢您添加您的答案;我相信这将有助于在未来的人@凯兰-打败了我。那是三年半前的事了。
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.");
}
}
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();