为了不重复几次,我想分解一些常见的东西。例如,假设我们有一头牛和一匹马。牛产奶,马跑得快,但两者都吃草。
public class Herbivorous
{
protected int Quantity;
public void EatGrass(int quantity)
{
var evt= Build.GrassEaten
.WithQuantity(quantity);
RaiseEvent(evt);
}
public void Apply(GrassEaten evt)
{
_quantity= evt.Quantity;
}
}
public class Horse : Herbivorous
{
private bool _HasFastRun;
public void RunFast()
{
var evt= Build.FastRun;
RaiseEvent(evt);
}
public void Apply(FastRunevt)
{
_HasFastRun= true;
}
}
public class Cow: Herbivorous
{
private bool _IsMilkProduced;
public void ProduceMilk()
{
var evt= Build.MilkProduced;
RaiseEvent(evt);
}
public void Apply(MilkProduced evt)
{
_IsMilkProduced= true;
}
}要吃草,我的应用程序接收Json或xml中的命令,或者任何反序列化到该类中的命令:
namespace Herbivorous
{
public class EatGrass : CommandBase
{
public Guid IdHerbivorous {get; set;}
public Guid CommitId {get; set;}
public long Version {get; set;}
public int Quantity {get; set;}
}
}命令处理程序应该是:
public class EatGrassHandler : CommandHandler<EatGrass>
{
public override CommandValidation Execute(EatGrass cmd)
{
Contract.Requires<ArgumentNullException>(cmd != null);
Herbivorous herbivorous= EventRepository.GetById<Herbivorous>(cmd.Id);
if (herbivorous.IsNull())
throw new AggregateRootInstanceNotFoundException();
herbivorous.EatGrass(cmd.Quantity);
EventRepository.Save(herbivorous, cmd.CommitId);
}
}到目前一切尚好。我有一个食草动物对象,我可以访问它的EatGrass函数,不管它是马还是牛,都不重要。唯一的问题是:
EventRepository.GetById<Herbivorous>(cmd.Id)事实上,让我们想象一下,我们有一头奶牛,它在早上产奶,现在想吃草。EventRepository包含一个事件MilkProduced,然后是命令EatGrass。有了CommandHandler,我们就不再是在奶牛面前了,食草者对产奶一无所知。它应该做些什么?
我是否应该有明确的上下文命令,比如:
namespace Herbivorous.Cow
{
public class EatGrass : CommandBase
{
public Guid IdHerbivorous {get; set;}
public Guid CommitId {get; set;}
public long Version {get; set;}
public int Quantity {get; set;}
}
public class ProduceMilk : CommandBase
{
public Guid IdHerbivorous {get; set;}
public Guid CommitId {get; set;}
public long Version {get; set;}
}
}这意味着,要求我的食草动物吃草的外部成分应该知道,在这种有限的范围内,我们谈论的是一头牛。在前一个命令中,我们讨论的是一种一般的食草动物行为,所以我电话的上下文并不重要。我们知道我们需要食草动物来吃草,仅此而已。
这是我的主要问题,可能是特定域从一个有界上下文泄漏到另一个上下文。实际上,这也可能意味着,在处理多个应用程序之间的接口时,我不能支持抽象。我想知道..。
或者当我重建我的食草动物时,我可以接受任何事情。这意味着,如果它找不到一个方法来应用这个事件,他将很好地尝试应用它的下一个流。这是真正的简单解决方案,但它并不能让我轻松地知道,事件可能不会被应用(并且不会产生错误)时,我的对象。(实际上,我想得越多,就越不觉得内疚。)
谢谢你的帮助,我才刚刚开始处理这类问题,我很高兴从更有经验的人那里得到一些消息。
发布于 2012-08-29 15:20:51
首先,将一个虚拟方法Execute(cmd)添加到您的Herbivorous中,并将用于将命令分派到那里的命令方法的代码放在那里。然后,Herbivorous的每个子类都可以覆盖该方法,并支持子类特有的所有命令方法。看起来应该是这样:
public class Cow: Herbivorous
{
public override void Execute(Command cmd)
{
if(cmd is ProduceMilkCommand)
ProduceMilk(cmd); // execute specific command
else
base.Execute(cmd); // delegate general commands to the base class
}
}为了从给定的命令中创建一个新的对象,将一个System.Type字段添加到您的cmd中,并使用反射来创建特定的Herbivorous子类型的实例。或者使用原型模式创建一个新实例(您的命令必须存储对该原型对象的引用)。第三种选择是使用抽象工厂模式,然后命令必须存储对正确工厂子类型的引用。
当然,如果您已经向我们展示了命令类当前的样子以及命令是如何创建的,我想我可以给您一个更好的答案。在代码片段中使用"var“命令隐藏了一些细节,这些细节对于一个更精确的答案可能很重要。
发布于 2013-08-14 04:01:20
https://softwareengineering.stackexchange.com/questions/162830
复制相似问题