Czy został już dodany moduł obsługi zdarzeń?

Czy istnieje sposób, aby stwierdzić, czy do obiektu został dodany moduł obsługi zdarzenia? Serializuję listę obiektów do stanu sesji/poza nim, abyśmy mogli używać stanu sesji bazującego na SQL... Gdy obiekt na liście ma zmienioną właściwość, musi zostać oznaczony, o co wcześniej zadbał Obsługa zdarzenia. Jednak teraz, gdy obiekty są deserializowane, nie otrzymuje obsługi zdarzenia.

W przypływie łagodnej irytacji, dodałem właśnie obsługę zdarzenia do Właściwości Get, która ma dostęp do obiekt. Jest wywoływany teraz, co jest Świetne, z wyjątkiem tego, że jest wywoływany z 5 razy, więc myślę, że handler jest dodawany za każdym razem, gdy obiekt jest dostępny.

To naprawdę wystarczająco bezpieczne, aby po prostu zignorować, ale wolałbym, aby było o wiele czystsze, sprawdzając, czy handler został już dodany, więc robię to tylko raz.

Czy to możliwe?

EDIT: niekoniecznie mam pełną kontrolę nad tym, jakie procedury obsługi zdarzeń są dodawane, więc po prostu sprawdzam, czy nie ma null to za mało.

Author: bdukes, 2008-09-26

7 answers

Poza klasą definiującą, jak wspomina @Telos, możesz używać Eventhandlera tylko po lewej stronie += lub -=. Tak więc, jeśli masz możliwość modyfikacji definiującej klasy, możesz podać metodę do wykonania sprawdzenia, sprawdzając, czy obsługa zdarzeń to null - jeśli tak, to nie dodano żadnej obsługi zdarzeń. Jeśli nie, to może i można w pętli przez wartości w Delegat.GetInvocationList . Jeśli jeden jest równy delegatowi, który chcesz dodać jako obsługę zdarzenia, więc wiesz, że tam jest.

public bool IsEventHandlerRegistered(Delegate prospectiveHandler)
{   
    if ( this.EventHandler != null )
    {
        foreach ( Delegate existingHandler in this.EventHandler.GetInvocationList() )
        {
            if ( existingHandler == prospectiveHandler )
            {
                return true;
            }
        }
    }
    return false;
}

I można to łatwo zmodyfikować, aby stało się"Dodaj obsługę, jeśli jej nie ma". Jeśli nie masz dostępu do wnętrzności klasy, która ujawnia Zdarzenie, być może będziesz musiał zbadać -= i +=, zgodnie z sugestią @Lou Franco.

Jednak może lepiej będzie ponownie zbadać sposób, w jaki uruchamiasz i likwidujesz te obiekty, aby sprawdzić, czy nie możesz znaleźć sposobu, aby samodzielnie wyśledzić te informacje.

 111
Author: Blair Conrad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 18:17:28

Ostatnio doszedłem do podobnej sytuacji, w której musiałem zarejestrować opiekuna do zdarzenia tylko raz. Odkryłem, że możesz bezpiecznie wyrejestrować się najpierw, a następnie zarejestrować ponownie, nawet jeśli handler nie jest zarejestrowany w ogóle:

myClass.MyEvent -= MyHandler;
myClass.MyEvent += MyHandler;

Zauważ, że robienie tego za każdym razem, gdy zarejestrujesz swój handler, zapewni, że Twój handler zostanie zarejestrowany tylko raz. Brzmi jak całkiem dobry trening dla mnie:)

 162
Author: alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-15 13:55:36

Jeśli jest to jedyna funkcja obsługi, możesz sprawdzić, czy zdarzenie jest null, jeśli nie, to funkcja obsługi została dodana.

Myślę, że możesz bezpiecznie wywołać - = na zdarzeniu ze swoim handlerem, nawet jeśli nie jest ono dodane (jeśli nie, możesz je złapać) -- aby upewnić się, że nie jest tam przed dodaniem.

 18
Author: Lou Franco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:58:11

Ten przykład pokazuje jak używać metody GetInvocationList () do pobierania delegatów do wszystkich programów obsługi, które zostały dodane. Jeśli chcesz zobaczyć, czy konkretna funkcja obsługi (funkcja) została dodana, możesz użyć array.

public class MyClass
{
  event Action MyEvent;
}

...

MyClass myClass = new MyClass();
myClass.MyEvent += SomeFunction;

...

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method

Możesz sprawdzić różne właściwości właściwości metody delegata, aby sprawdzić, czy dana funkcja została dodana.

Jeśli chcesz sprawdzić, czy jest tylko jeden dołączony, możesz po prostu przetestować na null.

 6
Author: Jason Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 17:29:51

Jeśli dobrze rozumiem twój problem, możesz mieć większe problemy. Powiedziałeś, że inne obiekty mogą być subskrybowane przez te wydarzenia. Gdy obiekt jest serializowany i deserializowany, inne obiekty (te, nad którymi nie masz kontroli) stracą swoje procedury obsługi zdarzeń.

Jeśli nie martwisz się o to, zachowywanie odniesienia do obsługi zdarzenia powinno być wystarczająco dobre. Jeśli obawiasz się skutków ubocznych innych obiektów tracących procedury obsługi zdarzeń, możesz chcieć przemyśl swoją strategię buforowania.

 4
Author: CodeChef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-17 16:04:30

Zgadzam się z odpowiedzią alfa, ale mała modyfikacja jest,, do użycia,

           try
            {
                control_name.Click -= event_Click;
                main_browser.Document.Click += Document_Click;
            }
            catch(Exception exce)
            {
                main_browser.Document.Click += Document_Click;
            }
 0
Author: Software_developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 10:25:33
EventHandler.GetInvocationList().Length > 0
 0
Author: benPearce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 12:53:10