How to dispatch events in C#
Asked Answered
K

4

21

I wish to create own events and dispatch them. I never done this before in C#, only in Flex.. I guess there must be a lot of differencies.

Can anyone provide me a good example?

Kyd answered 15/3, 2010 at 15:55 Comment(2)
WinForms, WebForms, ASP.NET MVC or WPF?Cupric
Thank you for all replies!! They helped me all together ;) Thanks again!!Kyd
B
49

There is a pattern that is used in all library classes. It is recommended for your own classes too, especially for framework/library code. But nobody will stop you when you deviate or skip a few steps.

Here is a schematic based on the simplest event-delegate, System.Eventhandler.

// The delegate type. This one is already defined in the library, in the System namespace
// the `void (object, EventArgs)` signature is also the recommended pattern
public delegate void Eventhandler(object sender, Eventargs args);  

// your publishing class
class Foo  
{
    public event EventHandler Changed;    // the Event

    protected virtual void OnChanged()    // the Trigger method, called to raise the event
    {
        // make a copy to be more thread-safe
        EventHandler handler = Changed;   

        if (handler != null)
        {
            // invoke the subscribed event-handler(s)
            handler(this, EventArgs.Empty);  
        }
    }

    // an example of raising the event
    void SomeMethod()
    {
       if (...)        // on some condition
         OnChanged();  // raise the event
    }
}

And how to use it:

// your subscribing class
class Bar
{       
    public Bar()
    {
        Foo f = new Foo();
        f.Changed += Foo_Changed;    // Subscribe, using the short notation
    }

    // the handler must conform to the signature
    void Foo_Changed(object sender, EventArgs args)  // the Handler (reacts)
    {
        // the things Bar has to do when Foo changes
    }
}

And when you have information to pass along:

class MyEventArgs : EventArgs    // guideline: derive from EventArgs
{
    public string Info { get; set; }
}

class Foo  
{
    public event EventHandler<MyEventArgs> Changed;    // the Event
    ...
    protected virtual void OnChanged(string info)      // the Trigger
    {
        EventHandler handler = Changed;   // make a copy to be more thread-safe
        if (handler != null)
        {
           var args = new MyEventArgs(){Info = info};  // this part will vary
           handler(this, args);  
        }
    }
}

class Bar
{       
   void Foo_Changed(object sender, MyEventArgs args)  // the Handler
   {
       string s = args.Info;
       ...
   }
}

Update

Starting with C# 6 the calling code in the 'Trigger' method has become a lot easier, the null test can be shortened with the null-conditional operator ?. without making a copy while keeping thread-safety:

protected virtual void OnChanged(string info)   // the Trigger
{
    var args = new MyEventArgs{Info = info};    // this part will vary
    Changed?.Invoke(this, args);
}
Binal answered 15/3, 2010 at 16:0 Comment(9)
I guess I can replace the EventArgs, with my own class?Kyd
Yes, though you'd use EventHandler<T> where T is the type of your event args aka.. public event EventHandler<MyOwnEventArgs> MyEvent;Camise
It is also a common .NET practice that your custom EventArgs class inherit from EventArgsCamise
@Henk: this would be an even better example using EventHandler<T> and an example EventArgs class.Arsenopyrite
@Janov: Additional information would go as parameter to OnChanged and then in a class derived from EventArgs. And then you can use EventHandler<MyEventArgs> as delegate.Binal
@John: Yes, that would have been more complete but I intentionally went for the minimum example.Binal
Just quick question. Can I make plugable architecture with this Event structure?Prosper
@Prosper - yes you could, but it's not the only solution. Make sure you know about interface too.Binal
@HenkHolterman Thank you so much for quick reply. Can you please guide me where can I start with that? how any reference sample project?Prosper
S
3

Events in C# use delegates.

public static event EventHandler<EventArgs> myEvent;

static void Main()
{
   //add method to be called
   myEvent += Handler;

   //call all methods that have been added to the event
   myEvent(this, EventArgs.Empty);
}

static void Handler(object sender, EventArgs args)
{
  Console.WriteLine("Event Handled!");
}
Surely answered 15/3, 2010 at 16:0 Comment(0)
C
3

Using the typical .NET event pattern, and assuming you don't need any special arguments in your event. Your typical event and dispatch pattern looks like this.

public class MyClassWithEvents
    {
        public event EventHandler MyEvent;

        protected void OnMyEvent(object sender, EventArgs eventArgs)
        {
            if (MyEvent != null)
            {
                MyEvent(sender, eventArgs);
            }
        }

        public void TriggerMyEvent()
        {
            OnMyEvent(sender, eventArgs);
        }
    }

Tying something into the event can be as simple as:

public class Program
{
    public static void Main(string[] args)
    {
        MyClassWithEvents obj = new MyClassWithEvents();

        obj.MyEvent += obj_myEvent;
    }

    private static void obj_myEvent(object sender, EventArgs e)
    {
        //Code called when my event is dispatched.
    }
}

Take a look at the links on this MSDN page

Camise answered 15/3, 2010 at 16:2 Comment(0)
C
0

Look into 'delegates'.

  • Define a delegate
  • Use the delegate type as field/property (adding the 'Event' keyword)
  • You are now exposing events that users can hook into with "+= MyEventMethod;"

Hope this helps,

Citrin answered 15/3, 2010 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.