在接口中使用事件

本文关键字:事件 接口 | 更新日期: 2023-09-27 18:25:13

我正在实现一个使用复合设计模式的菜单系统。我有以下MenuElement界面:

public interface MenuElement
{
    void AddMenuElement( MenuElement menuToAdd );
    void RemoveMenuElement( MenuElement menuToRemove );
    MenuElement GetMenuElement( int index );
    void Activate();
}

我想在这个接口中包含一个"OnActivate"事件,这样实现这个接口的MenuItems就可以在激活时触发函数。我试着这样实现它:

public interface MenuElement
{
    public delegate void MenuEvent();
    event MenuEvent onActivate;
    void AddMenuElement( MenuElement menuToAdd );
    void RemoveMenuElement( MenuElement menuToRemove );
    MenuElement GetMenuElement( int index );
    void Activate();
}

但是,编译器不允许我在接口内声明委托。我知道一个名为EventHandler的C#事件类型,但与我想要的MenuEvent不同,它需要object和EventArgs参数。我也考虑过将我的事件和委托转移到MenuItem,但我仍然很好奇是否可以让接口包含自定义事件。

这可能吗?或者在这种情况下,我必须使用C#的EventHandler类吗?

在接口中使用事件

为什么不使用EventHandler?例如

  // I've added "I" since it's an Interface
  public interface IMenuElement {
    void AddMenuElement(MenuElement menuToAdd);
    void RemoveMenuElement(MenuElement menuToRemove);
    void Activate();
    // I've changed your 
    // MenuElement GetMenuElement(int index)
    // to indexer
    MenuElement this[int index] {get;}
    // Event of interest; I've renamed it from onActivate
    event EventHandler Activated;
  }
  ...
  // Possible interface implementation
  public class MyMenuElement: IMenuElement {
    ...
    // name like "onActivate" is better to use here, as a private context
    private void onActivated() {
      if (Object.ReferenceEquals(null, Activated)) 
        return;
      Activated(this, EventArgs.Empty);
    }
    public void Activate() {
      // Some staff here
      ... 
      // Raising the event
      onActivated();
    }
  }

接口不是用来实现字段的;它是用来定义合同(签名)的,仅此而已。

如果你想提供一个基字段,结合一个"接口",可以考虑一个抽象类。抽象类对于提供部分实现非常有用。

public abstract class MenuElement
{
    public delegate void MenuEvent();
    event MenuEvent onActivate;
    abstract virtual void AddMenuElement( MenuElement menuToAdd );
    abstract virtual void Activate();
}

如果也有一个接口很重要,那么只需让MenuElement类继承该接口,并将其传递给其子代即可。抽象类可以在不实现接口的情况下继承接口,以便将它们传递给叶类,同时保持方便因素。

请记住,您也可以在接口中声明属性,但叶类仍然必须实现该属性。