문제

이벤트 구독을 취소해야 하는 사용 사례가 있습니다.하지만 구독을 취소하기 전에 이 사람이 실제로 이 이벤트에 접속했는지 여부를 확인하고 싶습니다.

어떻게 하면 이를 달성할 수 있는지 알려주세요.

도움이 되었습니까?

해결책

샘플 클래스 게시자는 하나의 이벤트 게시를 제공합니다. 이 메소드가 등록되면 주어진 클래스 인스턴스에 대한 이벤트 첨부 이벤트 핸들러를 쿼리 하고이 클래스 인스턴스에서 하나 이상 등록 / 첨부 된 이벤트 핸들러가있는 경우 TRUE를 반환합니다. 재정의 된 ISREGISTERED 메소드는 정적 유형에 대해 동일하게 수행합니다.

이 코드를 콘솔 애플리케이션 프로젝트에 넣고 F5를 눌러 디버그를 사용하여 시도해보십시오.

internal class Publisher
{
    internal event EventHandler<EventArgs> Publish;

    internal bool IsRegistered(Type type)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == null & item.Method.DeclaringType == type select item).Count() > 0;

    }
    internal bool IsRegistered(object instance)
    {
        if (Publish == null) return false;
        //
        return (from item in Publish.GetInvocationList() where item.Target == instance select item).Count() > 0;
    }

    static int Main(string[] args)
    {
        Publisher p = new Publisher();
        //
        p.Publish += new EventHandler<EventArgs>(static_Publish);
        p.Publish += new EventHandler<EventArgs>(p.instance_Publish);            
        //
        Console.WriteLine("eventhandler static_Publish attach: {0}", p.IsRegistered(typeof(Program)));
        Console.WriteLine("eventhandler instance_Publish attach: {0}", p.IsRegistered(program));
        //
        return 0;
    }

    void instance_Publish(object sender, EventArgs e)
    {

    }
    static void static_Publish(object sender, EventArgs e)
    {

    }
}`

다른 팁

에서 마이크로 소프트:

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Format the string to send inside the CustomEventArgs parameter
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());

                // Use the () operator to raise the event.
                handler(this, e);
            }
        }

당신은 찾고 있습니다 if (handler! = null) 부분. 이것의 없는 가입자가없는 경우 null이 아닙니다 가입자가있는 경우

펍/하위 환경을 가정하면 공급자에게 전화를 걸고 (EventType, 가입자) 공급자가 가입자가 구독되었는지 여부를 결정하도록하십시오.

이를 수행할 수 있는 두 가지 방법이 있습니다:

  1. 구독 취소 중인 대리인을 제거하여 새 대리인 체인을 생성하고 저장하기 전에 얻은 것과 비교할 수 있습니다.해당 대리인의 구독을 취소하는 경우 가지다 구독하면 해당 대리인 없이 새 대리인 체인을 다시 받게 됩니다.대리인의 구독을 취소하려는 경우 하지 않았다 구독하시면 기존 체인과 동일한 체인을 다시 받게 됩니다.
  2. 수동으로 대리인 체인을 탐색하여 구독 취소하려는 대리인이 있는지 확인할 수 있습니다.이는 다음과 같은 일반적인 Linq 방법을 사용하여 수행할 수 있습니다. .Contains 단순성을 위해.

첫 번째 경우는 아래 코드와 같습니다.이렇게 하면 임시 변수에 새 대리자 체인이 생성되고, 제거하려는 대리자를 사용하여 제거한 다음 임시 체인을 기존 체인과 비교합니다.동일하다면 대리인이 참석하지 않은 것입니다.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }
    remove
    {
        EventHandler temp = _Changed - value;
        if (_Changed == null || temp == _Changed)
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed = temp;
    }
}

아래 코드와 같은 두 번째는 구독을 취소하려는 대리인이 대리인 체인에 있는지 간단히 확인합니다.

private EventHandler _Changed;
public event EventHandler Changed
{
    add
    {
        _Changed += value;
    }

    remove
    {
        if (_Changed == null || !_Changed.GetInvocationList().Contains(value))
            throw new InvalidOperationException(
                "Delegate is not subscribed, cannot unsubscribe");
        _Changed -= value;
    }
}

원하는 경우 유사한 코드를 사용하여 대리자가 두 번 추가되는 경우를 처리할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top