Лучший способ обработки событий с несколькими классами?

#c# #events

#c# #Мероприятия

Вопрос:

Итак, у меня есть класс, который в основном является менеджером для более чем 20 копий другого класса. Каков наилучший способ обработки одного и того же события, запущенного из каждого из них? И это лучший способ отменить регистрацию событий? Или я должен каким-то образом использовать один обработчик событий?

Я собрал простой пример, который в основном делает то, что я делаю в моем реальном проекте.

 class Manager
{
    List<Child> children = new List<Child>();

    public Manager()
    {
        for (int i = 0; i < 10; i  )
        {
            Childchild = new Child();
            child.Done  = child_Done;
            items.Add(child);
            child.DoStuff();
        }
    }

    public void RemoveAll()
    {
        foreach (Child child in items)
        {
            child.Done -= child_Done;
        }
        items.Clear();
    }

    void child_Done(string sometext)
    {
        Console.WriteLine("child done: "   sometext);
    }
}

class Child
{
    public delegate void _Done(string sometext);
    public event _Done Done;

    public Child()
    {

    }

    public void DoStuff()
    {
        if (Done != null) { Done("finally!"); }
    }
}
  

Ответ №1:

Отмена регистрации должна быть в порядке — до тех пор, пока целевой экземпляр и метод совпадают, он будет работать. Однако я настоятельно рекомендую вам использовать более обычный шаблон событий с a sender — тогда вы будете знать, какой дочерний элемент разговаривает. Например:

 public class MessageEventArgs : EventArgs {
    public MessageEventArgs(string message) {
        this.message = message;
    }
    private readonly string message;
    public string Message { get { return message; } }
}
  

и:

 public event EventHandler<MessageEventArgs> Done;
protected virtual void OnDone(string message) {
    var handler = Done;
    if(handler != null) handler(this, new MessageEventArgs(message));
}
  

Ответ №2:

Предполагая, что вы хотите, возможно, было бы лучше добавить объект Manager для ответа каждому дочернему объекту, когда дочерний объект вызывает событие:

Возможно, было бы лучше зарегистрироваться для события при добавлении дочернего элемента и отменить регистрацию при удалении дочернего элемента.

Быстрый способ сделать это — переключиться с List на ObservableCollection . Эта коллекция вызовет событие, как только коллекция изменится.

Итак, в конструкторе менеджера создайте экземпляр ObservableCollection и зарегистрируйтесь для события CollectionChanged . В обработчике проверьте аргумент события, чтобы увидеть, какие дочерние элементы были добавлены и удалены, чтобы менеджер мог зарегистрировать (или отменить регистрацию) их событие (события).

Ответ №3:

Это более или менее так.
Несколько предложений, чтобы заставить его работать немного лучше:

  1. Создайте функцию, которая добавляет дочерний элемент и одновременно регистрирует событие.
    То же самое можно сделать с удалением дочернего элемента отменой регистрации события.
  2. Кроме того, вы можете заставить событие получить параметр «sender» и заставить дочерний элемент передать ему «this». Таким образом, обработчик событий сможет узнать, какой дочерний элемент выполнен, и удалить его из списка, и / или что еще нужно сделать.