[C#] 이벤트 핸들러가 이미 추가 되었습니까?

이벤트 핸들러가 객체에 추가되었는지 알 수있는 방법이 있습니까? SQL 기반 세션 상태를 사용할 수 있도록 객체 목록을 세션 상태로 / 외부에서 직렬화하고 있습니다 … 목록의 객체에 속성이 변경되면 플래그를 지정해야합니다. . 그러나 이제 객체가 직렬화 해제되면 이벤트 핸들러가 표시되지 않습니다.

약간의 불편 함을 느끼기 위해 방금 객체에 액세스하는 Get 속성에 이벤트 핸들러를 추가했습니다. 5 번처럼 호출되는 것을 제외하고는 지금 훌륭하게 호출됩니다. 따라서 객체에 액세스 할 때마다 핸들러가 계속 추가된다고 생각합니다.

그냥 무시할 정도로 안전하지만 처리기가 이미 추가되었는지 확인하여 한 번만 수행하면 훨씬 더 깨끗하게 만들 수 있습니다.

가능합니까?

편집 : 이벤트 처리기가 추가되는 것을 완전히 제어 할 필요는 없으므로 null을 확인하는 것만으로는 충분하지 않습니다.



답변

@Telos가 언급했듯이 정의 클래스 외부에서 a +=또는 a 의 왼쪽에서만 EventHandler를 사용할 수 있습니다 -=. 따라서 정의 클래스를 수정하는 기능이 있으면 이벤트 핸들러가 있는지 확인하여 점검을 수행하는 메소드를 제공 할 수 있습니다. null그렇다면 이벤트 핸들러가 추가되지 않은 것입니다. 그렇지 않으면 아마도 Delegate.GetInvocationList 의 값을 반복 할 수 있습니다
. 하나가 이벤트 핸들러로 추가하려는 대리자와 같으면 거기에 있음을 알 수 있습니다.

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

그리고 “핸들러가없는 경우 추가”가되도록 쉽게 수정할 수 있습니다. 당신이 이벤트를 노출하는 것 클래스의 내장에 액세스 할 수없는 경우, 당신은 탐구해야 -=하고 +=@Lou 프랑코에 의해 제안.

그러나 이러한 정보를 직접 추적하는 방법을 찾을 수 없는지 확인하기 위해 이러한 오브젝트를 커미셔닝 및 해제하는 방법을 다시 검토하는 것이 좋습니다.


답변

최근에 이벤트 처리기를 한 번만 등록 해야하는 비슷한 상황이 발생했습니다. 핸들러가 전혀 등록되지 않은 경우에도 먼저 안전하게 등록을 취소 한 다음 다시 등록 할 수 있습니다.

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

핸들러를 등록 할 때마다이 작업을 수행하면 핸들러가 한 번만 등록됩니다. 나에게 꽤 좋은 연습처럼 들린다 🙂


답변

이것이 유일한 핸들러 인 경우 이벤트가 null인지 확인하고 그렇지 않은 경우 핸들러가 추가되었는지 확인할 수 있습니다.

처리기가 추가되지 않은 경우에도 처리기를 사용하여 이벤트에서-=을 안전하게 호출 할 수 있다고 생각합니다. 추가하지 않으면 잡을 수 없습니다.


답변

이 예제는 GetInvocationList () 메소드를 사용하여 추가 된 모든 핸들러에 대한 델리게이트를 검색하는 방법을 보여줍니다. 특정 핸들러 (함수)가 추가되었는지 확인하려면 배열을 사용할 수 있습니다.

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

델리게이트의 Method 속성에서 다양한 속성을 검사하여 특정 함수가 추가되었는지 확인할 수 있습니다.

하나만 첨부되어 있는지 확인하려면 null을 테스트하면됩니다.


답변

문제를 올바르게 이해하면 더 큰 문제가있을 수 있습니다. 다른 객체가이 이벤트를 구독 할 수 있다고 말했습니다. 객체가 직렬화되고 역 직렬화되면 다른 객체 (제어 할 수없는 객체)의 이벤트 핸들러가 손실됩니다.

걱정하지 않는다면 이벤트 핸들러에 대한 참조를 유지하는 것이 좋습니다. 이벤트 핸들러를 잃은 다른 오브젝트의 부작용에 대해 걱정이된다면 캐싱 전략을 다시 생각할 수 있습니다.


답변

나를 위해 일한 유일한 방법은 이벤트를 추가 할 때 true로 설정 한 부울 변수를 만드는 것입니다. 그런 다음 묻습니다. 변수가 false이면 이벤트를 추가합니다.

bool alreadyAdded = false;

이 변수는 전역적일 수 있습니다.

if(!alreadyAdded)
{
    myClass.MyEvent += MyHandler;
    alreadyAdded = true;
}


답변

나는 alf의 답변에 동의하지만 그것에 약간의 수정은 사용하는 것입니다.

           try
            {
                control_name.Click -= event_Click;
                main_browser.Document.Click += Document_Click;
            }
            catch(Exception exce)
            {
                main_browser.Document.Click += Document_Click;
            }