子/父事件引发

本文关键字:事件 | 更新日期: 2023-09-27 18:16:48

我有一个父抽象类和几个子类。最后,我希望在子类中完成的进度通过GUI中的进度条显示。

我现在所做的,我意识到将不起作用,是在父类中声明的事件方法定义作为每个子类将覆盖的虚拟方法。比如:

public abstract class Parent
{
 public event EventHandler someEvent;
 protected virtual void OnSomeEvent(object sender, EventArgs e)
    {
          EventHandler eh= someEvent;
        if (eh!= null)
        {
            eh(this, e);
        }
    }
}

我的子类是这样的:

  protected override void OnSomeEvent(object sender, EventArgs e)
    {
        base.OnSomeEvent(sender, e);
    }

,事件在子类的某处引发。

然而,由于父类是抽象的,我将无法从GUI中侦听事件,因为我无法创建抽象类的实例。

我完全偏离了方向和/或有其他方法做到这一点吗?

子/父事件引发

您可以从子实例中附加到事件。

public abstract class Parent
{
      public event Action Something;
      public void OnSomething()
      {
          if (Something != null)
          {
              Something();
          }
      }
}
public class Child : Parent
{
}
Child c = new Child();
c.Something += () => Console.WriteLine("Got event from child");
c.OnSomething();
> Got event from child

您甚至可以将其声明为包含子类型的Parent类型:

Parent c2 = new Child();
c2.Something += () => Console.WriteLine("Got event from Parent type");
c2.OnSomething();
> Got event from Parent type
抽象类只是一个代码模板,它被复制到从它继承的每个类中(简单地说)。可以这样想,所有的Child类都包含Parent中存在的代码的相同副本。

注意,这还将为Child的每个实例生成一个唯一的事件处理程序。为所有源自ParentChild设置一个静态事件处理程序,如下所示,并且不需要在Child中编写任何代码:

public abstract class Parent
{
    public static event Action Something;
    public static void OnSomething()
    {
        if (Something != null)
        {
            Something();
        }
    }
}

然后,你可以这样做,例如:

Parent.Something += () => Console.WriteLine("This will be invoked twice.");
Child c = new Child();
Child c2 = new Child();
c.OnSomething();
c2.OnSomething();
> This will be invoked twice.
> This will be invoked twice.

这两个对象/事件调用将调用相同的事件处理程序,即使它们来自不同的子节点。

首先不要,因为someEvent没有指定static,所以子类的每个实例都将有自己的someEvent。这意味着你得到的不是一个统一的观点,而是一个多元化的观点。这对于响应按钮被按下很有用,因为你不想在他们点击背景时以同样的方式响应。

通常不使用类层次结构,而是使用组合来处理这种情况。例如,将以下类添加到您的类:

public class ParentContainer
{
    private List<Parent> watched = new List<Parent>();
    public void Add(Parent watch)
    {
        watched.Add(watch);
        watch.SomeEvent += Handler;
    }
    private void Handler(object sender, EventArgs args)
    {
        //Do something
    }
}