在运行时重新分配事件处理程序

时间:2013-03-04 20:31:05

标签: c# delegates event-handling

我想在运行时更改附加到BackgroundWorker的委托。下面会有类似的工作吗?

DoWorkEvenHandler dweh = new DoWorkEventHandler(method1);
backgroundworker.DoWork += dweh;

稍后通过重新分配引用DoWork来更改与dweh相关联的委托:

dweh = new DoWorkEventHandler(method2);

2 个答案:

答案 0 :(得分:8)

不,您不能将委托“分配”给事件处理程序。处理程序通过将事件添加到内部用于表示事件的基础委托的调用列表来附加到事件。这是设计的!

不,您不能通过更改先前用于附加事件处理程序的引用所指向的对象来更改处理程序;部分是因为委托是不可变的,部分是因为你只是将引用改为指向别的东西,而不是真正改变你想要完成的事件处理程序。

为了更改委托,您必须先删除上一个委托:

backgroundworker.DoWork -= dweh;

然后通过将其添加为事件的处理程序来分配新的:

backgroundworker.DoWork += new DoWorkEventHandler(method2);

注意

在大多数情况下,您可以使用以下语法从事件中删除处理程序(委托):

backgroundworker.DoWork -= new DoWorkEventHandler(mehtod1);

或使用隐式或显式方法组转换:

backgroundworker.DoWork -= (DoWorkEventHandler)mehtod1;  // explicit convertion    
//  -  or  - 
backgroundworker.DoWork -= mehtod1;                      // implicit (more compact)

但是根据情况,您可能需要维护对前一个委托的引用,以便以后能够删除它。例如,这将适用于匿名方法或lambda表达式。

答案 1 :(得分:0)

你可以用众所周知的“额外的间接水平”来解决这个问题。写一个这样的课:

public sealed class RedirectableDoWorkEventHandler
{
    public RedirectableDoWorkEventHandler(DoWorkEventHandler handler)
    {
        Contract.Requires(handler != null);
        _handler = handler;
    }

    public DoWorkEventHandler Handler
    {
        get
        {
            return _handler;
        }

        set
        {
            Contract.Requires(value != null);
            _handler = value;
        }
    }

    public void DoWork(object sender, DoWorkEventArgs e)
    {
        _handler(sender, e);
    }

    private DoWorkEventHandler _handler;
}

然后你可以使用这样的东西:

public void Setup()
{
    BackgroundWorker worker = new BackgroundWorker();

    // ...

    var handler = new RedirectableDoWorkEventHandler(handler1);

    worker.DoWork += handler.DoWork;

    // And then some time later...

    handler.Handler = handler2; // Now DoWork will call handler2.
}

private void handler1(object sender, DoWorkEventArgs e)
{
    // Whatever
}

private void handler2(object sender, DoWorkEventArgs e)
{
    // Whatever
}

但实际上,重点是什么?您可能只有一个带有if的简单处理程序,可以在选项中进行选择。我想在某些情况下可以帮助封装东西...... YMMV。