Подтвердить что ты не робот

Избегайте дублирования подписки на события в С#

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

theOBject.TheEvent += RunMyCode;

В моем установщике делегата я могу эффективно запустить это...

theOBject.TheEvent -= RunMyCode;
theOBject.TheEvent += RunMyCode;

но лучший способ?

4b9b3361

Ответ 1

Я думаю, самый эффективный способ - сделать ваше событие свойством и добавить к нему блокировки concurrency, как в этом Пример

private EventHandler _theEvent;
private object _eventLock = new object();
public event EventHandler TheEvent
{
    add
    {
        lock (_eventLock) 
        { 
            _theEvent -= value; 
            _theEvent += value; 
        }
    }
    remove
    {
        lock (_eventLock) 
        { 
           _theEvent -= value; 
        }
    }
}

Ответ 2

Я сделал это раньше... он предполагает, что приемлемо, что последним подписчиком является то, что вызвано.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            MyObject my = new MyObject();
            my.Changed += new EventHandler(my_Changed);
            my.Changed += new EventHandler(my_Changed1);

            my.Update();
            Console.ReadLine();
        }

        static void my_Changed(object sender, EventArgs e)
        {
            Console.WriteLine("Hello");
        }
        static void my_Changed1(object sender, EventArgs e)
        {
            Console.WriteLine("Hello1");
        }
    }
    public class MyObject
    {
        public MyObject()
        {
        }
        private EventHandler ChangedEventHandler;
        public event EventHandler Changed
        {
            add
            {
                ChangedEventHandler = value;
            }
            remove
            {
                ChangedEventHandler -= value;
            }
        }
        public void Update()
        {
            OnChanged();
        }

        private void OnChanged()
        {
            if (ChangedEventHandler != null)
            {
                ChangedEventHandler(this, null);
            }
        }
    }
}

Ответ 3

Является ли ваш код многопоточным? Concurrency Блокировка необходима только при многопоточности. Если это не накладные расходы.

Таким образом, ваш подход к отписке и подписке является правильным.

Спасибо

Ответ 4

Если у вас есть источник для класса объекта, у вас есть доступ к InvocationList из TheEvent. Вы можете реализовать свой собственный add accessor для события и проверить перед добавлением.

Однако, я думаю, что ваш подход тоже прекрасен.

Ответ 5

Я использую ваш подход, кроме одной детали. Я думаю, что события должны быть подписаны при создании нового экземпляра подписчика или объекта, это делает код более прямым. Таким образом, все, что вам нужно, - это просто внимательно следить за правильным размещением объектов (распоряжаться паттеном для этого удобно).

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