如何确定事件是否已订阅

Ram*_*Ram 52 .net c#

在我的.NET应用程序中,我订阅了来自另一个类的事件.订阅是有条件的.我在控件可见时订阅事件,在它变得不可见时取消订阅.但是,在某些情况下,我不想取消订阅事件,即使控件不可见,因为我想要在后台线程上发生的操作的结果.

有没有办法确定一个类是否已经订阅了该事件?

我知道我们可以在类中通过检查事件来引发该事件null,但是我如何在订阅该事件的类中执行它?

Han*_*ant 66

event关键字是明确发明的,以防止您做您想做的事情.它限制对底层delegate对象的访问,因此没有人可以直接处理它存储的事件处理程序订阅.事件是委托的访问者,就像属性是字段的访问者一样.属性只允许get和set,事件只允许添加和删除.

这使代码安全,其他代码只有在知道事件处理程序方法和目标对象时才能删除事件处理程序.C#语言通过不允许您命名目标对象来增加额外的安全层.

并且WinForms提供了额外的安全层,因此即使您使用Reflection也会变得困难.它将delegate实例存储在EventHandlerList带有秘密"cookie"的密钥中,您必须知道cookie才能将对象从列表中挖出.

好吧,不要去那里.用你的一些代码解决你的问题是微不足道的:

private bool mSubscribed;

private void Subscribe(bool enabled)
{
    if (!enabled) textBox1.VisibleChanged -= textBox1_VisibleChanged;
    else if (!mSubscribed) textBox1.VisibleChanged += textBox1_VisibleChanged;

    mSubscribed = enabled;
}
Run Code Online (Sandbox Code Playgroud)

  • 哦,给我一些信用,要知道当这个用户谈论控制时,他的意思是[winforms].从他的个人资料中不难发现. (8认同)
  • 您是否碰巧有任何博客,频道9视频或msdn文章谈论使*事件*难以与之交互的设计方法?也许如果我理解了*为什么*,以及用于实现某些(通常)琐碎事物的*预期*机制,我可能会更容易为我自己的问题集提出简单的解决方案. (4认同)
  • 如果有多个订阅者怎么办?我不想两次注册同一个订户......我不希望任何单个订阅者触发两次事件.当订户是远程实体时,通过wcf信道,问题也是相关的. (3认同)
  • 您的活动不难与之互动.与其他人的*事件混淆是困难的,这是私人部分的混乱.问一个关于它的问题. (2认同)
  • 好吧,*为什么*搞乱其他人的事件很困难? (2认同)

Gor*_*pik 7

假设您无法访问声明事件的类的内部,您无法直接执行此操作.活动只会暴露运营商+=-=,没有别的.您需要在订阅类中使用标志或其他机制来了解您是否已订阅.


SwD*_*n81 6

  /// <summary>
  /// Determine if a control has the event visible subscribed to
  /// </summary>
  /// <param name="controlObject">The control to look for the VisibleChanged event</param>
  /// <returns>True if the control is subscribed to a VisibleChanged event, False otherwise</returns>
  private bool IsSubscribed(Control controlObject)
  {
     FieldInfo event_visible_field_info = typeof(Control).GetField("EventVisible",
        BindingFlags.Static | BindingFlags.NonPublic);
     object object_value = event_visible_field_info.GetValue(controlObject);
     PropertyInfo events_property_info = controlObject.GetType().GetProperty("Events",
        BindingFlags.NonPublic | BindingFlags.Instance);
     EventHandlerList event_list = (EventHandlerList)events_property_info.GetValue(controlObject, null);
     return (event_list[object_value] != null);
  }
Run Code Online (Sandbox Code Playgroud)