public void DeliverEvent(object sender, EventArgs e)
{
}
public void StartListening(Button source)
{
source.Click += DeliverEvent;
}
public void StartListening(EventHandler eventHandler)
{
eventHandler += DeliverEvent;
}
但是在#2中,你无法调用该方法,因为如果你尝试这样的话:
StartListening(button.Click);
您收到此错误:
The event 'System.Windows.Forms.Control.Click' can only appear on the left hand side of += or -=
有没有解决这个错误的方法?我希望能够将事件而非事件的对象传递给StartListening
方法。
答案 0 :(得分:1)
您不能将事件作为参数传递,因为它不是委托类型的对象。事件是一对两种方法 - add
和remove
。
即。按钮类的Click
事件实际上看起来像
public void add_Click(EventHandler value)
{
// combine delegate
}
public void remove_Click(EventHandler value)
{
// remove delegate
}
如果要订阅事件,则应传递整个对象,然后为该特定事件调用add
方法(使用+=
语法)。
答案 1 :(得分:1)
您正在与代表混合活动。你应该阅读Jon Skeet的this文章,它将解释两者之间的差异。
第二个选项不起作用的原因是因为该方法需要一个符合EventHandler
签名的委托参数。Button.Click
指的是事件而不是委托。事件只是封装代表。
我不确定你的尝试是做什么的。从概念上讲,你想要做的事实际上并没有意义;它是处理程序的逻辑,而不是事件本身。
查看this帖子,了解模拟所需效果的一些方法。
答案 2 :(得分:0)
Microsoft Reactive Extensions或Rx框架提供了将事件转换为可观察对象的方法。事件不能作为参数传递,但是可观察事件可以。当订阅观察者时,他们为基础事件设置处理程序。
签名(其中一个重载)如下所示:
IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(
Action<TDelegate> addHandler, Action<TDelegate> removeHandler
) where TEventArgs: EventArgs
例如,要从事件中定义MouseMove
observable,可以使用此代码:
IObservable<EventPattern<MouseEventArgs>> mouseMoves =
Observable
.FromEventPattern<MouseEventHandler, MouseEventArgs>(
h => richTextBox1.MouseMove += h,
h => richTextBox1.MouseMove -= h);
然后,您可以传递对IObservable<EventPattern<MouseEventArgs>> mouseMoves
的引用并订阅它,如下所示:
var subscription =
mouseMoves
.Subscribe(ep =>
{
var x = ep.EventArgs.X;
var y = ep.EventArgs.Y;
// etc
});
从observable / event中分离就像调用它一样简单:
subscription.Dispose();
你可以通过Nuget获得Rx。
答案 3 :(得分:0)
不幸的是,尽管.net中的事件和属性存在于类型系统中,虽然对于Microsoft来说它们既可以作为具体类型存在也是可行的(每个实例都包含一对委托,用于添加/ remove或for get / set),微软没有创建任何这样的具体类型,也没有看到这样做。因此,没有一种远程好看的方式将属性或事件传递给例程。相反,对于事件,要么必须传递一对委托 - 一个用于Add
方法,一个用于Remove
方法,或者可能传递一个包含两个委托的类或结构有问题,或者传递应该使用其事件的对象以及事件的名称,并让被调用的例程使用Reflection来找到与命名事件关联的添加/删除处理程序。