2011-11-03 57 views
0

假设我们有下面的类结构:听继承类的特定事件

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中的每一种新事件似乎都不是我的解决方案。

+0

这是一个家庭作业吗? –

+0

不,我正在试图找到一种方法,不要创建一个巨大的农场类。 – Marnix

+0

为什么不添加一个枚举来描述一个农民可能感兴趣的东西。这与农民不需要了解具体的水果事件有什么不同。但有了相当大的优势,你现在只需要一个事件。 –

回答

1

只是让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不同的方法。

+0

这听起来很有希望。我将讨论我的团队中的可能性。 – Marnix

+0

这可能是完美的答案,但不幸的是,我们有更多的需求,这种模式无法促成。例如。人们也应该能够订阅所有事件,而不知道这些事件是什么。但对于我问的问题,这将是一个正确的实施。谢谢。 – Marnix

+0

好的,谢谢你的接受。根据您的一般要求:最终需要做出关于“Farmer”应该订阅哪些事件的决定,因此尽管您可以隐藏来自“Farmer”本身的行为需要居住在某处的知识。如果这个责任似乎不适合你的任何现有对象,那么也许这表明你需要引入一个新的类来履行这个角色。祝你好运。 –

0

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

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的启发。

+0

你会离开所有这些命令处理程序吗?它看起来像一个很好的模式,但我不明白这不会显着增加'Farm'代码,因为每个新事件需要Farm中的一个新的CommandHandler来订阅。 – Marnix

+0

你的逻辑是这样的,你会在你的应用程序中有很多代码。这只是一个类有很多代码的问题,因为许多类都有一些代码。在上面的模式中,您可以编写一个订阅管理器类,其中包含哪个服务器场订阅哪个命令处理程序的逻辑。 – Suhas

0

那么,如果农场有水果,那么它只能订阅水果事件。

在您的基类中定义一个虚拟事件,即Fruit,然后在您的不同Fruits子类中覆盖它,就像苹果一样,它会是FallFromTree。

看到这个更多详情 C#: What are virtual events and how can they be used?

+0

这会极大地增加水果类,也意味着任何一种水果都会知道如何从树上掉下来,而一些水果甚至不会从树上长出来。所以,这只是一个巨大农场的解决方法。 – Marnix

+0

不,我的意思是Fruit类会有一个称为ChildEvent的通用事件。每个孩子都会以自己的方式暴露它。就像苹果将暴露FallFromTree for ChildEvent一样。其他水果将根据其属性覆盖他们自己的儿童活动。就像在根中生长的水果一样,会暴露出GrownFromRoot – Anand

+0

但是这意味着每个水果只能有一个事件。这当然不是这种情况。我希望他们也有多个活动。 – Marnix