在C#中转发事件

use*_*891 46 c# events event-handling c#-2.0

我正在使用一个在C#中转发事件的类.我想知道是否有一种方法可以减少代码开销.

这是我到目前为止所拥有的一个例子.

class A
{
   public event EventType EventA;
}

class B
{
   A m_A = new A();
   public event EventType EventB;

   public B()
   {
      m_A.EventA += OnEventA;
   }

   public void OnEventA()
   {
      if( EventB )
      {
         EventB();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

A级引发原始事件.B类将其转发为EventB(基本上是同一事件).A类对其他模块是隐藏的,因此无法直接订阅EventA.

我正在尝试做的是减少B类中用于转发事件的代码开销,因为通常没有真正处理类B中的事件.此外,我将有几个不同的事件,因此需要编写大量的OnEvent ()B类中仅用于转发事件的方法.

是否有可能以某种方式自动将EventA链接到EventB,所以我会有这样的事情:

class B
{
   A m_A = new A();
   public event EventType EventB;

   public B()
   {
      m_A.EventA += EventB; // EventA automatically raises EventB.
   }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用C#2.0编译器btw.

Jon*_*eet 83

绝对:

class B
{
    private A m_a = new A();

    public event EventType EventB
    {
        add { m_a.EventA += value; }
        remove { m_a.EventA -= value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,Eve​​ntB订阅/取消订阅代码只是将订阅/取消订阅请求传递给EventA.

请注意,这不允许您仅为订阅EventB的订阅者引发事件.这就像将某人的地址直接传递给大众营销公司,而您原来的方式更像是自己订阅大众营销公司,并允许人们要求您将邮件的副本发送给他们.

  • 这确实意味着"B.EventB"的订阅者得到了错误的发送者(`A`而不是'B`) - 这可能很重要...... (17认同)
  • 真实,真实......当然,取决于你认为"错误"的东西.可能至少值得记录. (8认同)

Mar*_*ell 11

IMO,您的原始代码(或多或少)正确.特别是,它允许您提供正确的sender(这应该是B认为他们订阅事件的人的实例B).

如果事件未订阅,有一些技巧可以减少运行时的开销,但这会增加更多代码:

class B {
   A m_A = new A();
   private EventType eventB;
   public event EventType EventB {
       add { // only subscribe when we have a subscriber ourselves
           bool first = eventB == null;
           eventB += value;
           if(first && eventB != null) m_A.EventA += OnEventB;
       }
       remove { // unsubscribe if we have no more subscribers
           eventB -= value;
           if(eventB == null) m_A.EventA -= OnEventB;
       }
   }

   protected void OnEventB(object sender, EventArgsType args) {
      eventB?.Invoke(this, args); // note "this", not "sender"

   }
}
Run Code Online (Sandbox Code Playgroud)