Практическое руководство. Публикация событий, соответствующих рекомендациям .NET Framework (Руководство по программированию в C#)

В следующей процедуре показано добавление событий, соответствующих стандартному шаблону .NET Framework для пользовательских классов и структур. Все события в библиотеке классов .NET Framework основаны на делегате EventHandler, заданном следующим образом:

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

Примечание

.NET Framework 2,0 представляет общую версию данного делегата EventHandler.В следующих примерах показано, как использовать обе версии.

Хотя события в задаваемых классах могут быть основаны на действительном типе делегата, даже на делегатах, возвращающих значение, обычно рекомендуется основывать события на шаблоне .NET Framework, используя EventHandler, как показано в следующем примере.

Порядок публикации событий, основанных на шаблоне EventHandler

  1. (Пропустите этот шаг и перейдите к шагу 3a, если не требуется передавать с событием пользовательские данные.) Объявите класс для пользовательских данных в области, видимой для классов издателя и подписчика. Затем добавьте необходимые члены для хранения данных пользовательских событий. В данном примере возвращается простая строка.

    public class CustomEventArgs : EventArgs
    {
        public CustomEventArgs(string s)
        {
            msg = s;
        }
        private string msg;
        public string Message
        {
            get { return msg; }
        } 
    }
    
  2. (Пропустите данный шаг, если используется общая версия EventHandler .) Объявите делегат в своем классе публикации. Назначьте ему имя, заканчивающееся на EventHandler. Второй параметр задает ваш тип EventArgs.

    public delegate void CustomEventHandler(object sender, CustomEventArgs a);
    
  3. Объявите событие в своем классе публикации с помощью одного из следующих действий.

    1. Если пользовательский класс EventArgs отсутствует, ваш тип Event представляет собой не являющийся общим делегат EventHandler. Этот делегат не нужно объявлять, так как он уже объявлен в пространстве имен System, добавленном при создании проекта C#. Добавьте следующий код в класс издателя.

      public event EventHandler RaiseCustomEvent;
      
    2. При использовании не универсальной версии типа EventHandler и наличии пользовательского класса, производного от типа EventArgs, объявите событие внутри класса публикации и используйте делегат из пункта 2 в качестве типа.

      public event CustomEventHandler RaiseCustomEvent;
      
    3. Если используется универсальная версия, то пользовательский делегат не требуется. Вместо этого в классе публикации необходимо задать тип события как EventHandler<CustomEventArgs>, заключив имя пользовательского класса в угловые скобки.

      public event EventHandler<CustomEventArgs> RaiseCustomEvent;
      

Пример

В следующем примере демонстрируются предыдущие шаги с применением пользовательского класса EventArgs и типа EventHandler в качестве типа события.

namespace DotNetEvents
{
    using System;
    using System.Collections.Generic;

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

        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }

    // 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("Did something"));

        }

        // 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> handler = RaiseCustomEvent;

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

                // Use the () operator to raise the event.
                handler(this, e);
            }
        }
    }

    //Class that subscribes to an event 
    class Subscriber
    {
        private string id;
        public Subscriber(string ID, Publisher pub)
        {
            id = ID;
            // Subscribe to the event using C# 2.0 syntax
            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: {0}", e.Message);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Publisher pub = new Publisher();
            Subscriber sub1 = new Subscriber("sub1", pub);
            Subscriber sub2 = new Subscriber("sub2", pub);

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

            // Keep the console window open
            Console.WriteLine("Press Enter to close this window.");
            Console.ReadLine();

        }
    }
}

См. также

Ссылки

События (Руководство по программированию в C#)

Делегаты (Руководство по программированию на C#)

Delegate

Основные понятия

Руководство по программированию на C#