监听继承类的特定事件

本文关键字:事件 继承 监听 | 更新日期: 2023-09-27 18:13:06

假设我们有以下类结构:

public class Fruit
{
    public event EventHandler<RipeEventArgs> Ripe;
}
public class Apple:Fruit
{
    public event EventHandler<FallEventArgs> FallFromTree;
}
public class Farm
{
    List<Fruit> fruits;
}
public class Farmer
{
    private Farm myFarm;
    public Farmer()
    {
        // listen to all FallFromTree events coming from the farm
        myFarm.WHAT += AppleFallen;
    }
    public void AppleFallen(object sender, FallEventArgs e) {}
}

问题:我如何确保农民可以从农场上的任何苹果和将来将要创建的任何苹果中听到所有的FallFromTree事件?

我正在考虑单独的冒泡事件,但这意味着Farm应该定义Apple也涵盖的每个事件。问题是,我将用不同的事件创造许多不同的水果,重要的是,一些特殊的农民只能听到来自农场的特定事件。所以在Farm中定义每一种新的事件对我来说似乎不是一个解决方案。

监听继承类的特定事件

Farm知道Farmer而不是Farmer知道Farm

public class Fruit
{
    public event EventHandler<RipeEventArgs> Ripe;
}
public class Apple:Fruit
{
    public event EventHandler<FallEventArgs> FallFromTree;
}
public class Farm
{
    List<Fruit> fruits;
    Farmer farmer;
    public Farm(Farmer farmer)
    {
        this.farmer = farmer;
    }
    public void AddFruit(Fruit fruit)
    {
        farmer.RegisterForEvents(fruit);
        fruits.Add(fruit);
    }
}
public class Farmer
{
    private Farm myFarm;
    public Farmer()
    {
    }
    public virtual void RegisterForEvents(Fruit fruit)
    {
       //Farmer decides what events it is interested in: can override in derived classes
       if(fruit is Apple)
       {
           ((Apple)fruit).FallFromTree += AppleFallen;
       }
    }
    public void AppleFallen(object sender, FallEventArgs e) {}
}

fruit is Apple子句不是理想的,但我认为你唯一能做的就是实现双重调度或在Farmer上为每种类型的Fruit使用不同的方法。

您需要实现一个命令处理程序来处理这些命令。让苹果掉下来是命令的一个例子。

public class MakeAppleFallCommandHandler
{
    public void Execute(Apple apple)
    {
      //This method would be called whenever any apple in the farm falls
      FallFromTree(apple);
    }
    public event EventHandler<FallEventArgs> FallFromTree;
}

然后在农民类中,您可以订阅MakeAppleFallCommandHandler.FallFromTree。灵感来自CQRS

如果Farm有水果,那么它只能订阅来自水果的事件。

在你的基类中定义一个虚拟事件,比如Fruit,然后在不同的Fruits子类中重写它,比如苹果,它将是FallFromTree。

查看更多详细信息c#:什么是虚拟事件?如何使用它们?