C# 如何查明是否有人订阅了活动?

C# 如何查明是否有人订阅了活动?,c#,event-handling,events,C#,Event Handling,Events,我有一个用例,我必须取消订阅一个活动。但在退订之前,我想确定这家伙是否真的迷上了这个活动 请告诉我如何实现这一点?假设是发布/订阅环境,只需呼叫提供商。取消订阅(EventType,subscriber)并让提供商确定订户是否已从以下位置订阅: //在受保护的虚拟方法中包装事件调用 //允许派生类重写事件调用行为 受保护的虚拟void OnRaiseCustomEvent(CustomEventArgs e) { //制作事件的临时副本,以避免 //最后一个订户取消订阅时的竞争条件 //在空检查

我有一个用例,我必须取消订阅一个活动。但在退订之前,我想确定这家伙是否真的迷上了这个活动


请告诉我如何实现这一点?

假设是发布/订阅环境,只需呼叫提供商。取消订阅(EventType,subscriber)并让提供商确定订户是否已从以下位置订阅:

//在受保护的虚拟方法中包装事件调用
//允许派生类重写事件调用行为
受保护的虚拟void OnRaiseCustomEvent(CustomEventArgs e)
{
//制作事件的临时副本,以避免
//最后一个订户取消订阅时的竞争条件
//在空检查之后和引发事件之前。
EventHandler=RaiseCustomEvent;
//如果没有订阅服务器,则事件将为null
if(处理程序!=null)
{
//格式化要在CustomEventArgs参数内发送的字符串
e、 Message+=String.Format(“at{0}”,DateTime.Now.ToString());
//使用()运算符引发事件。
处理者(本,e);
}
}

您正在寻找if(handler!=null)部分。如果没有订阅者,则为null;如果有订阅者,则为null。

示例类发布者提供一个事件发布。方法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)
    {

    }
}`
内部类发布器
{
内部事件处理程序发布;
内部布尔值已注册(类型)
{
if(Publish==null)返回false;
//
返回(来自Publish.GetInvocationList()中的项,其中item.Target==null&item.Method.DeclaringType==type选择项)。Count()>0;
}
内部bool已注册(对象实例)
{
if(Publish==null)返回false;
//
返回(来自Publish.GetInvocationList()中的项,其中item.Target==实例选择项)。Count()>0;
}
静态int Main(字符串[]args)
{
Publisher p=newpublisher();
//
p、 Publish+=新事件处理程序(静态发布);
p、 Publish+=新事件处理程序(p.instance\u Publish);
//
WriteLine(“eventhandler static_Publish attach:{0}”,p.IsRegistered(typeof(Program));
WriteLine(“eventhandler实例_发布附加:{0}”,p.IsRegistered(程序));
//
返回0;
}
无效实例发布(对象发送方,事件参数e)
{
}
静态无效静态发布(对象发送方、事件参数)
{
}
}`

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

  • 您可以创建一个新的代理链,删除取消订阅的代理,并将其与保存前获得的代理链进行比较。如果您取消订阅已订阅的委托,您将获得一个新的委托链,而没有该委托。如果您试图取消订阅一个尚未订阅的代理,您将获得与之前相同的链
  • 您可以手动遍历代理链,查看要取消订阅的代理是否存在。为了简单起见,可以使用常规的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;
        }
    }
    

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

    这是一个非常特定于环境的问题-因此您应该提供一些关于语言/框架/平台的信息。您需要编辑您的问题,提供有关您的问题的更多信息。哦,这是来自C。下面是详细信息:假设有一个类a提供了一个事件ABC,而另一个类B已经注册了该事件。现在在某个方法中,我需要取消B的订阅。但是在取消订阅之前,我想确定这个家伙是否真的订阅了这个活动。现在我该怎么做呢?虽然你的帖子是准确的,但他想检查他是否已经为事件分配了特定的处理程序,而不是是否分配了任何处理程序(即,它不是null)。是的,Silky是正确的。我想知道是否已经附加了处理程序。当我们注册一个事件时,每次我们都会建立一个新的委托实例,这样我就不会让委托获取调用列表。不是吗?我们不查询委托实例本身,而是查询其上的目标属性。我们想知道类A是否已将事件处理程序注册到我们的事件(多播委托),因此我们查询事件上所有已注册的委托,以查找在目标属性中包含类A实例的委托,希望这能有所帮助
    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;
        }
    }