如何判断某人是否订阅了某个活动?

时间:2009-09-10 03:52:31

标签: c# event-handling events

我有一个用例,我必须取消订阅活动。但是在取消订阅之前,我想确定这个人是否已经真正地吸引了这个事件。

请告诉我如何实现这一目标?

4 个答案:

答案 0 :(得分:3)

来自Microsoft

        // 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 ,如果有订阅者,则 not null

答案 1 :(得分:1)

示例类Publisher提供一个事件Publish。 IsRegistered方法查询给定类实例的事件附加事件处理程序,如果此类实例至少有一个注册/附加事件处理程序,则返回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)
    {

    }
}`

答案 2 :(得分:0)

假设有一个pub / sub环境,只需调用provider.Unsubscribe(EventType,subscriber)并让提供者确定订阅者是否订阅

答案 3 :(得分:0)

有两种方法可以做到这一点:

  1. 您可以创建一个新的委托链,删除取消订阅的委托,并与保存之前的委托进行比较。如果您取消订阅订阅的代理,您将返回一个新的委托链,而不是该委托。在您尝试取消订阅尚未订阅的代理的情况下,您将获得与您拥有的链相同的链。
  2. 您可以手动遍历委托链,以查看是否存在要取消订阅的委托。为简单起见,可以使用常规Linq方法(如.Contains)来完成此操作。
  3. 第一种情况看起来像下面的代码。这将在临时变量中创建一个新的委托链,其中包含要删除,删除的委托,然后将临时链与现有链进行比较。如果它们是相同的,代表就不在场。

    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;
        }
    }
    

    请注意,如果需要,您可以使用类似的代码来处理两次添加委托的情况。