Friday 1 April 2011

Dot.Net: Expose Custom Events

Question:
How do I expose custom events in a c# class?
How do I create custom event, event delegate, event arguments in dot.net?



Answer:
The following code creates a class JokeDetector that scans a source (web) for jokes.
When it finds one it triggers a jokeDetected event.
The event is based on a delegate : jokeDelegate that uses our custom EventArgs : JokeEventArgs class to store the joke.

Finally, an instance of the JokeCustomer class can subscribe to the jokeDetected event.

Here is an example
public class JokeDetector
{
    // the delegate defines the signature of the callbacks that can subscribe to our event
    public delegate void jokeDelegate(JokeEventArgs b);

    // the event is typed with our funny delegate
    public event jokeDelegate jokeDetected;

    // that simulates a method that will search for jokes on the web or wherever ...
    public void ScanWebForJokes()
    {
        // your code to crawl the web and detect jokes
        ...
        string joke = "Why did the bald man paint rabbits on his head? Because from a distance they looked like hares!";
        // call the event
        OnJokeDetected(new JokeEventArgs { JokeText = joke });
        ...
    }

    // By convention you should create a protected virtual event handler method
    // That allows classes that inherit from this class to handle the event
    protected virtual void OnJokeDetected(JokeEventArgs args)
    {
        if (jokeDetected != null)
        {
            jokeDetected(args);
        }
    }

}

// custom event args have the advantage that you can store whatever you want. Even jokes.
public class JokeEventArgs : EventArgs
{
    public string JokeText { get; set; }
}

// This simulates an event subscriber
public class JokeCustomer
{
    public JokeCustomer(JokeDetector jdetect)
    {
        jdetect.jokeDetected += new JokeDetector.jokeDelegate(jdetect_jokeDetected);
    }

    void jdetect_jokeDetected(JokeEventArgs b)
    {
        Console.WriteLine("We have found a joke. It goes like: " + b.JokeText);
    }
}


That was not a joke.
happy programing ...

Here is an example for Guillaume with a generic EventHandler which takes JokeEventArgs as type argument.
public static void Main(string[] args)
{
    JokeDetector jd = new JokeDetector();
    JokeCustomer jc = new JokeCustomer(jd);
    jd.ScanWebForJokes();

}
public class JokeDetector
{
    // the event is typed with our funny delegate
    public event EventHandler<JokeEventArgs> jokeDetected;

    // that simulates a method that will search for jokes on the web or wherever ...
    public void ScanWebForJokes()
    {
        // your code to crawl the web and detect jokes

        string joke = "Why did the bald man paint rabbits on his head? Because from a distance they looked like hares!";
        // call the event
        OnJokeDetected(new JokeEventArgs { JokeText = joke });

    }

    // By convention you should create a protected virtual event handler method
    // That allows classes that inherit from this class to handle the event
    protected virtual void OnJokeDetected(JokeEventArgs args)
    {
        if (jokeDetected != null)
        {
            jokeDetected(this, args);
        }
    }

}

public class JokeEventArgs : EventArgs
{
    public string JokeText { get; set; }
}

// This simulates an event subscriber
public class JokeCustomer
{
    public JokeCustomer(JokeDetector jdetect)
    {
        jdetect.jokeDetected += new EventHandler<JokeEventArgs>(jdetect_jokeDetected);
    }

    void jdetect_jokeDetected(object sender, JokeEventArgs e)
    {
        Console.WriteLine("We have found a joke. It goes like: " + e.JokeText);
    }
 
}

2 comments:

Anonymous said...

You can get rid of
public delegate void jokeDelegate(JokeEventArgs b);
and declare the event as
public event EventHandler jokeDetected;


Guillaume

jens said...

well done. yes, but you might want to use a generic EventHandler in order to customize you EventArgs.