누군가가 이벤트를 구독했는지 확인하는 방법은 무엇입니까?
-
05-07-2019 - |
문제
이벤트 구독을 취소해야 하는 사용 사례가 있습니다.하지만 구독을 취소하기 전에 이 사람이 실제로 이 이벤트에 접속했는지 여부를 확인하고 싶습니다.
어떻게 하면 이를 달성할 수 있는지 알려주세요.
해결책
샘플 클래스 게시자는 하나의 이벤트 게시를 제공합니다. 이 메소드가 등록되면 주어진 클래스 인스턴스에 대한 이벤트 첨부 이벤트 핸들러를 쿼리 하고이 클래스 인스턴스에서 하나 이상 등록 / 첨부 된 이벤트 핸들러가있는 경우 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, 가입자) 공급자가 가입자가 구독되었는지 여부를 결정하도록하십시오.
이를 수행할 수 있는 두 가지 방법이 있습니다:
- 구독 취소 중인 대리인을 제거하여 새 대리인 체인을 생성하고 저장하기 전에 얻은 것과 비교할 수 있습니다.해당 대리인의 구독을 취소하는 경우 가지다 구독하면 해당 대리인 없이 새 대리인 체인을 다시 받게 됩니다.대리인의 구독을 취소하려는 경우 하지 않았다 구독하시면 기존 체인과 동일한 체인을 다시 받게 됩니다.
- 수동으로 대리인 체인을 탐색하여 구독 취소하려는 대리인이 있는지 확인할 수 있습니다.이는 다음과 같은 일반적인 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;
}
}
원하는 경우 유사한 코드를 사용하여 대리자가 두 번 추가되는 경우를 처리할 수 있습니다.