Override Runtime Event Handler

I want to change the delegate attached to BackgroundWorker at runtime. Would something like below work?

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

and at some point later change the delegate associated with DoWork by reassigning the dweh link:

 dweh = new DoWorkEventHandler(method2); 
+4
source share
2 answers

No, you cannot "assign" a delegate to an event handler. Handlers are attached to events, adding them to the call list of the main delegate, which is used internally to represent the event. This is by design!

And no, you cannot change the handler by changing the object pointed to by the link previously used to attach the event handler; partly because delegates are immutable , and partly because you just change the link to point to something else without changing the event handler you are trying to execute.

To change a delegate, you must first delete the previous delegate:

 backgroundworker.DoWork -= dweh; 

Then assign a new one, adding it as an event handler:

 backgroundworker.DoWork += new DoWorkEventHandler(method2); 

Note

In most cases, you can remove the handler (delegate) from the event using this syntax:

 backgroundworker.DoWork -= new DoWorkEventHandler(mehtod1); 

or using implicit or explicit method group transformation:

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

But depending on the situation, you may need a link to the previous delegate to subsequently delete it. For example, this applies to anonymous methods or lambda expressions.

+8
source

You can solve this with the notorious โ€œextra level of indirectionโ€. Write the class as follows:

 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; } 

And then you can use it something like this:

 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 } 

But really, what's the point? You can just have one simple handler with if to select one of the options. I believe this can help encapsulate things in some cases ... YMMV.

0
source

All Articles