Guide pratique pour publier des événements conformes aux lignes directrices de .NET (Guide de programmation C#)

La procédure suivante montre comment ajouter des événements qui respectent le modèle .NET standard à vos classes et structs. Tous les événements de la bibliothèque de classes .NET sont basés sur le délégué EventHandler, qui est défini comme suit :

public delegate void EventHandler(object? sender, EventArgs e);

Notes

.NET Framework 2.0 comprend une version générique de ce délégué, EventHandler<TEventArgs>. Les exemples suivants montrent comment utiliser les deux versions.

Bien que les événements des classes que vous définissez puissent être basés sur n’importe quel type délégué valide, même les délégués qui retournent une valeur, il est généralement recommandé de baser vos événements sur le modèle .NET à l’aide de EventHandler, comme indiqué dans l’exemple suivant.

Le nom EventHandler peut entraîner un peu de confusion, car il ne gère pas réellement l’événement. Le EventHandler et EventHandler<TEventArgs> générique sont des types délégués. Une méthode ou une expression lambda dont la signature correspond à la définition du délégué est le gestionnaire d’événements et est appelée lorsque l’événement est déclenché.

Pour publier des événements basés sur le modèle EventHandler

  1. (Ignorez cette étape et passez à l’étape 3a si vous n’avez pas besoin d’envoyer des données personnalisées avec votre événement.) Déclarez la classe pour vos données personnalisées dans une étendue visible à la fois par vos classes d’éditeur et d’abonné. Ajoutez ensuite les membres nécessaires pour contenir vos données d’événement personnalisées. Dans cet exemple, une simple chaîne est retournée.

    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string message)
        {
            Message = message;
        }
    
        public string Message { get; set; }
    }
    
  2. (Ignorez cette étape si vous utilisez la version générique de EventHandler<TEventArgs>.) Déclarez un délégué dans votre classe de publication. Donnez-lui un nom qui se termine par EventHandler. Le deuxième paramètre spécifie votre type EventArgs personnalisé.

    public delegate void CustomEventHandler(object? sender, CustomEventArgs args);
    
  3. Déclarez l’événement dans votre classe de publication en effectuant l’une des étapes suivantes.

    1. Si vous n’avez aucune classe EventArgs personnalisée, votre type d’événement sera le délégué EventHandler non générique. Il est inutile de déclarer le délégué, car il l’est déjà dans l’espace de noms System inclus au moment où vous créez votre projet C#. Ajoutez le code suivant à votre classe de serveur de publication.

      public event EventHandler? RaiseCustomEvent;
      
    2. Si vous utilisez la version non générique de EventHandler et que vous avez une classe personnalisée dérivée de EventArgs, déclarez votre événement à l’intérieur de votre classe de publication et utilisez votre délégué de l’étape 2 comme type.

      public event CustomEventHandler? RaiseCustomEvent;
      
    3. Si vous utilisez la version générique, vous n’avez pas besoin de délégué personnalisé. Au lieu de cela, dans votre classe de publication, vous spécifiez votre type d’événement en tant que EventHandler<CustomEventArgs>, en insérant le nom de votre propre classe entre les crochets.

      public event EventHandler<CustomEventArgs>? RaiseCustomEvent;
      

Exemple

L’exemple suivant est une illustration des étapes précédentes avec l’utilisation d’une classe EventArgs personnalisée et de EventHandler<TEventArgs> comme type d’événement.

namespace DotNetEvents
{
    // Define a class to hold custom event info
    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string message)
        {
            Message = message;
        }

        public string Message { get; set; }
    }

    // Class that publishes an event
    class Publisher
    {
        // Declare the event using EventHandler<T>
        public event EventHandler<CustomEventArgs>? RaiseCustomEvent;

        public void DoSomething()
        {
            // Write some code that does something useful here
            // then raise the event. You can also raise an event
            // before you execute a block of code.
            OnRaiseCustomEvent(new CustomEventArgs("Event triggered"));
        }

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<CustomEventArgs>? raiseEvent = RaiseCustomEvent;

            // Event will be null if there are no subscribers
            if (raiseEvent != null)
            {
                // Format the string to send inside the CustomEventArgs parameter
                e.Message += $" at {DateTime.Now}";

                // Call to raise the event.
                raiseEvent(this, e);
            }
        }
    }

    //Class that subscribes to an event
    class Subscriber
    {
        private readonly string _id;

        public Subscriber(string id, Publisher pub)
        {
            _id = id;

            // Subscribe to the event
            pub.RaiseCustomEvent += HandleCustomEvent;
        }

        // Define what actions to take when the event is raised.
        void HandleCustomEvent(object? sender, CustomEventArgs e)
        {
            Console.WriteLine($"{_id} received this message: {e.Message}");
        }
    }

    class Program
    {
        static void Main()
        {
            var pub = new Publisher();
            var sub1 = new Subscriber("sub1", pub);
            var sub2 = new Subscriber("sub2", pub);

            // Call the method that raises the event.
            pub.DoSomething();

            // Keep the console window open
            Console.WriteLine("Press any key to continue...");
            Console.ReadLine();
        }
    }
}

Voir aussi