C # - есть метод, нужно удалить или обнаружить все события, которые ссылаются на него - PullRequest
1 голос
/ 02 июля 2010

У меня есть метод, который на протяжении всей жизни моего приложения добавляется к любому количеству событий. В какой-то момент я хотел бы удалить метод из всех событий, которые ссылаются на него. Я знаю только метод ... Я хотел бы НЕ хранить локальные List<EventHandler> всех событий, к которым добавляется метод, потому что я думаю, что где-то / как-то CLR делает это для меня в целях сбора мусора. Какой-нибудь псевдокод ниже, есть идеи? Спасибо ...

Что я хочу сделать:

public class Subscriber
{
  public virtual void EventRaised(object pSender, EventArgs pArguments)
  {
    MessageBox.Show("EventRaised");
  }

  public virtual void UnsubscribeAll()
  {
    //Something like:
    EventRaised.RemoveReferences();
    //or
    foreach(var MyReference in EventRaised.References)
      MyReference.Remove();
  }
}

var MySubscriber = new Subscriber();

ThisEvent += MySubscriber.EventRaised;
ThatEvent += MySubscriber.EventRaised;
//on and on...

MySubscriber.UnsubscribeAll();

Что я не хочу делать:

public class Subscriber
{
  protected List<EventHandler> Publishers = new List<EventHandler>();

  public virtual void EventRaised(object pSender, EventArgs pArguments)
  {
    MessageBox.Show("EventRaised");
  }

  public virtual void Subscribe(EventHandler pPublisher)
  {
    pPublisher += EventRaised;
    Publishers.Add(pPublisher);
  }

  public virtual void UnsubscribeAll()
  {
    foreach(var Publisher in Publishers)
      Publisher -= EventRaised;

    Publishers.Clear();
  }
}

var MySubscriber = new Subscriber();

MySubscriber.Subscribe(ThisEvent);
MySubscriber.Subscribe(ThatEvent);
//on and on...

MySubscriber.UnsubscribeAll();

Другой пример

Если CLR не отслеживает ссылки на Стивена Клири - облом ... что вынуждает меня составить план B. Ответы и комментарии не совсем соответствуют моей проблеме - хотя я виноват, поэтому добавлю другой пример ниже. Пример кода JBall № 1 очень интересен, и я добавлю это в мою сумку трюков.

Я не удаляю ссылки на события для метода с необходимостью или намерением восстановить их позже ... Я просто хочу, чтобы они исчезли. Как насчет этого псевдокода - с точки зрения Ребенка, я хочу сказать: «забудь о любых событиях, к которым присоединен мой Родитель, и присоединяйся к этим событиям». У меня есть несколько обходных путей, включая сохранение List<> прикрепленных событий, но я надеялся использовать работу, которую CLR выполняет для меня за кулисами. Дополнительным преимуществом структуры, поддерживаемой CLR, был бы тот факт, что она является окончательной и окончательной ... не было бы возможности присоединить метод к событию без фактической записи ссылки.

public class Parent
{
  public Parent()
  {
    AnObject.ThisEvent += EventRaised;
    AnObject.ThatEvent += EventRaised;
  }

  public virtual void EventRaised(object pSender, EventArgs pArguments)
  {
    MessageBox.Show("EventRaised");
  }
}

public class Child
{
  public Child(): base()
  {
    //What I want to do:
    EventRaised.RemoveAllEventReferences();

    AnotherObject.ThisEvent += EventRaised;
    AnotherObject.ThatEvent += EventRaised;
  }
}

1 Ответ

1 голос
/ 02 июля 2010

Пусть ваш метод EventRaised вызывает другого делегата, которого вы назначаете по умолчанию, а когда вызывается UnsubscribeAll(), удалите это событие из вашего внутреннего делегата.

public class Subscriber
{
    EventHander m_InnerEvent;

    public Subscriber()
    {
        m_InnerEvent += InnerEventRaised;
    }

    public virtual void EventRaised(object pSender, EventArgs pArguments)
    {
        m_InnerEvent(pSender, pArguments);
    }

    protected virtual void InnerEventRaised(object pSender, EventArgs pArguments)
    {
        Console.WriteLine("EventRaised");
    }

    public virtual void UnsubscribeAll()
    {
        m_InnerEvent -= InnerEventRaised;
    }
}

В качестве альтернативы, установите флаг,установите при вызове UnsubscribeAll() и проверьте этот флаг в вашем методе EventRaised.

public class Subscriber
{
    bool m_Active = true;

    public virtual void EventRaised(object pSender, EventArgs pArguments)
    {
        if(m_Active) { InnerEventRaised(pSender, pArguments); }
    }

    void InnerEventRaised(object pSender, EventArgs pArguments)
    {
        Console.WriteLine("EventRaised");
    }

    public virtual void UnsubscribeAll()
    {
        m_Active = false;
    }
}

Для вашего нового примера, если это на самом деле структура того, что вы пытаетесь сделать, вы простонужно рефакторинг.Все происходит в конструкторах, и конструктор Child просто отменяет то, что было сделано в конструкторе Parent.Переместите биты действий родительского конструктора в метод.Затем Child может переопределить этот метод, чтобы пропустить то, что будет делать Parent, и вместо этого делать то, что он хочет:

public class Parent
{
    public Parent()
    {
        AttachEventsToThings();
    }

    protected virtual void AttachEventsToThings()
    {
        AnObject.ThisEvent += EventRaised;
        AnObject.ThatEvent += EventRaised;
    }

    public virtual void EventRaised(object pSender, EventArgs pArguments)
    {
        MessageBox.Show("EventRaised");
    }
}

public class Child : Parent
{
    protected override void AttachEventsToThings()
    {
        AnotherObject.ThisEvent += EventRaised;
        AnotherObject.ThatEvent += EventRaised;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...