views:

528

answers:

1

I had once a situation where I had to override the event handler in some derived class of mine. I could not unfortunately just "override" it since the implementation logic was bound strictly to that particular method implementation in the base class.

My natural idea was to first "unbind" the original event handler from the event and then to bind my own brand-new method. So I tried to use the "-=" operator like:

myObject.SomeEvent -= new EventHandler (BaseClass.SomeEventHandler)

at which point the compiler complainer that it had no access to the private method SomeEventHandler. Since the base class was a part of the library I did not really want to modify its implementation (though simply as it seems by just turning "private" into "protected");

It's so simple to attach an event handler to an event. Why is it so difficult to get rid of one?

Why I wanted it? Because the base implementation was casing some problems (just did not handle our particular case) so I wanted to redefine it. But even after I attached my event handler the base implementation was getting executed anyway. Since it was doing some kind of Redirect, my own implementation was never going to run since the request processing was being broken at server after redirect.

Is there anyway to get rid of an event handler in a base class from a library without modifying its implementation?

+3  A: 

It would be just as easy to get rid of the handler if your code can officially see the handler. If absolutely necessary, it is possible to unsubscribe using reflection to get hold of the delegate, but this is messy. It would be a lot cleaner and safer to either a: avoid the requirement, or b: change the code to make the handler protected.


Reflection approach (use at own risk); uncomment the block in the Bar.ctor() to see the change.

using System;
class Foo
{
    public event EventHandler SomeEvent;
    public Foo()
    {
        SomeEvent += SecretHandler; // a bad idea, anyway
                                    //(self-subscribed events....)
    }
    protected virtual void OnSomeEvent()
    {
        EventHandler handler = SomeEvent;
        if (handler != null) handler(this, EventArgs.Empty);
    }
    private void SecretHandler(object sender, EventArgs args)
    {
        Console.WriteLine("suscribed");
    }
}
class Bar : Foo
{
    public Bar()
    {
        /*
        MethodInfo method = typeof(Foo).GetMethod("SecretHandler",
            BindingFlags.NonPublic | BindingFlags.Instance);
        EventHandler handler = (EventHandler)Delegate.CreateDelegate(
            typeof(EventHandler), this, method);
        SomeEvent -= handler;
         */
    }
    public void Test()
    {
        OnSomeEvent();
    }
}
static class Program
{
    static void Main()
    {
        Bar bar = new Bar();
        bar.Test();
    }
}
Marc Gravell
Isn't there a way to get rid of just all the attached handlers without having access to them? Just let the system secretly from you identify and unbind them all?
User
Will you be so kind as to show how to do it using reflection?
User