确保只有一个委托绑定到一个事件

本文关键字:一个 事件 有一个 绑定 确保 | 更新日期: 2023-09-27 18:15:51

我正在绑定进程的退出事件。我为该事件的进程设置了一个复选框,该进程决定在运行exit事件时发生什么。如果我在进程运行时选中复选框,它将获取进程并添加退出事件。如果Process未运行,则启动该进程并添加exit事件。如果复选框未选中,无论进程是否正在运行,我都不执行任何操作。

我的问题是,如果进程正在运行,我选中框(它得到一个事件),取消选中框(没有发生任何设计),然后重新选中框,然后进程得到两个退出事件(这是完全相同的方法)。如果我有Process对象,如果它已经有退出事件,我怎么能不添加退出事件呢?

确保只有一个委托绑定到一个事件

根据这个微软论坛帖子http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/45071852-3a61-4181-9a25-068a8698b8b6/你可以只是删除现有的处理程序之前,你再次分配它。

要获取订阅邀请的所有委托的数组,只需使用GetInvoacationList方法。从那里你可以检查它的长度或迭代它来检查事件将调用多少/哪些委托。

 Delegate[] delegates = MyEvent.GetInvocationList();

根据你实际要做的事情,你似乎可以这样做;

  if (MyEvent.GetInvocationList().Length > 0)

 if (MyEvent.GetInvoationList().Contains(referenceToMyDelegate))

使用-=操作符将事件与委托分离。

就像你将事件绑定到委托一样:

EventHandler foo = new EventHandler(this._onClick)
myButton.Click += foo;

你也可以这样做,如果你把引用保存在某个地方:

myButton.Click -= foo;

当事件被触发时,它不再调用foo.

当复选框被选中时,你可能会这样做:

foo.Exited += new EventHandler(your_method);

这样,每次选中该框时,都会得到一个与事件绑定的新处理程序。只使用一个处理程序。这样,当复选框未被选中时,您可以-=之前与退出事件相关联的委托。

Edit:既然您想要的只是保持委托引用的方法不做任何事情,为什么不在检查事件之外的某个点将委托绑定到事件,然后使用方法中的复选框状态来选择是否运行方法的其余部分或停止它并提前返回?

试试这个:

delegate void MyDelegate(string message);
class Foo
{
    MyDelegate _delegate = null;
    int _count = 0;
    public event MyDelegate MySingleDelegateEvent
    {
        add
        {
            if (_count == 0)
            {
                _delegate += value;
                _count++;
            }
        }
        remove
        {
            if (_delegate != null)
            {
                _delegate -= value;
                _count--;
            }
        }
    }
}

如果你必须查看事件,你可以使用反射:

class Program
{
    static void Main(string[] args)
    {
        var car = new Car();
        car.Stopped += car_Stopped;
        var evt = car.GetType().GetEvent("Stopped");
        if(evt == null) //evt will be null if nothing is registered to the event
            car.Stopped += car_Stopped;
        car.Stop(); //Prints 'Stopped!' only once
        Console.ReadLine();
    }
    static void car_Stopped(object sender, EventArgs e)
    {
        Console.WriteLine("Stopped!");
    }
}
class Car
{
    public event EventHandler<EventArgs> Stopped;
    protected void OnStopped()
    {
        var temp = Stopped;
        if(temp != null)
            Stopped(this, new EventArgs());
    }
    public void Stop()
    {
        OnStopped();
    }
}