Publikování událostí, které odpovídají pokynům pro .NET (Průvodce programováním v C#)

Následující postup ukazuje, jak přidat události, které se řídí standardním vzorem .NET do tříd a struktur. Všechny události v knihovně tříd .NET jsou založeny na delegátu EventHandler , který je definován takto:

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

Poznámka:

Rozhraní .NET Framework 2.0 zavádí obecnou verzi tohoto delegáta . EventHandler<TEventArgs> Následující příklady ukazují, jak používat obě verze.

I když události ve třídách, které definujete, mohou být založeny na libovolném platném typu delegáta, i delegáty, které vracejí hodnotu, obecně doporučujeme založit události na vzoru .NET, EventHandlerjak je znázorněno v následujícím příkladu.

Název EventHandler může vést k trochu nejasnostem, protože ve skutečnosti nezpracuje událost. A EventHandlerobecné EventHandler<TEventArgs> jsou typy delegátů. Metoda nebo výraz lambda, jehož podpis odpovídá definici delegáta , je obslužná rutina události a bude vyvolána při vyvolání události.

Publikování událostí na základě vzoru Obslužná rutina událostí

  1. (Tento krok přeskočte a přejděte ke kroku 3a, pokud s událostí nemusíte odesílat vlastní data.) Deklarujte třídu pro vlastní data v oboru, který je viditelný jak pro vaše třídy vydavatele, tak pro předplatitele. Potom přidejte požadované členy, které budou uchovávat vlastní data událostí. V tomto příkladu se vrátí jednoduchý řetězec.

    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string message)
        {
            Message = message;
        }
    
        public string Message { get; set; }
    }
    
  2. (Tento krok přeskočte, pokud používáte obecnou verzi EventHandler<TEventArgs>souboru .) Deklarujte delegáta ve třídě publikování. Pojmenujte ho, který končí EventHandler. Druhý parametr určuje váš vlastní EventArgs typ.

    public delegate void CustomEventHandler(object? sender, CustomEventArgs args);
    
  3. Deklarujte událost ve třídě publikování pomocí jednoho z následujících kroků.

    1. Pokud nemáte vlastní třídu EventArgs, váš typ události bude negenerovaný delegát EventHandler. Delegáta nemusíte deklarovat, protože je již deklarován v System oboru názvů, který je součástí vytváření projektu jazyka C#. Do třídy vydavatele přidejte následující kód.

      public event EventHandler? RaiseCustomEvent;
      
    2. Pokud používáte ne generickou verzi EventHandler a máte vlastní třídu odvozenou z EventArgs, deklarujte událost uvnitř třídy publikování a jako typ použijte svého delegáta z kroku 2.

      public event CustomEventHandler? RaiseCustomEvent;
      
    3. Pokud používáte obecnou verzi, nepotřebujete vlastního delegáta. Místo toho ve třídě publikování zadáte typ události jako EventHandler<CustomEventArgs>nahrazení názvu vlastní třídy mezi úhlové závorky.

      public event EventHandler<CustomEventArgs>? RaiseCustomEvent;
      

Příklad

Následující příklad ukazuje předchozí kroky pomocí vlastní Třídy EventArgs a EventHandler<TEventArgs> jako typ události.

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

Viz také