在为聚合重放事件时,您如何将Apply这些事件发送到子(非根)实体.
到目前为止,我有两个关于如何解决这个问题的想法.
你采取了哪些方法,哪些方法有效,哪些无效?
在我的搜索中,我只发现了两个讨论问题的链接(两者都采用了第一种方法):
作为上述讨论的参与者之一,我可以分享一些见解.如果你看一下像NCQRS这样的项目,它正式化了实体如何以一种相当明确的方式构建和补充水平,你会发现这种方法存在一定的刚性.对于实体,我发现我将存储作为聚合状态从简单的字段,列表或字典演变为专用的集合类,具体取决于维护它们的分散行为.较小的刚性带来自由,在总体边界内选择建模.我非常重视这一点.
补液时事件的路由发生在聚合体内部.这不应该是IMO外化的东西.有各种方法可以解决它.在我自己的项目中,这是我以非常轻量级的方式将其形式化(仅在此处显示的实体):
/// <summary>
/// Base class for aggregate entities that need some basic infrastructure for tracking state changes on their aggregate root entity.
/// </summary>
public abstract class Entity : IInstanceEventRouter
{
readonly Action<object> _applier;
readonly InstanceEventRouter _router;
/// <summary>
/// Initializes a new instance of the <see cref="Entity"/> class.
/// </summary>
/// <param name="applier">The event player and recorder.</param>
/// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="applier"/> is null.</exception>
protected Entity(Action<object> applier)
{
if (applier == null) throw new ArgumentNullException("applier");
_applier = applier;
_router = new InstanceEventRouter();
}
/// <summary>
/// Registers the state handler to be invoked when the specified event is applied.
/// </summary>
/// <typeparam name="TEvent">The type of the event to register the handler for.</typeparam>
/// <param name="handler">The state handler.</param>
/// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="handler"/> is null.</exception>
protected void Register<TEvent>(Action<TEvent> handler)
{
if (handler == null) throw new ArgumentNullException("handler");
_router.ConfigureRoute(handler);
}
/// <summary>
/// Routes the specified <paramref name="event"/> to a configured state handler, if any.
/// </summary>
/// <param name="event">The event to route.</param>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="event"/> is null.</exception>
public void Route(object @event)
{
if (@event == null) throw new ArgumentNullException("event");
_router.Route(@event);
}
/// <summary>
/// Applies the specified event to this instance and invokes the associated state handler.
/// </summary>
/// <param name="event">The event to apply.</param>
protected void Apply(object @event)
{
if (@event == null) throw new ArgumentNullException("event");
_applier(@event);
}
}
Run Code Online (Sandbox Code Playgroud)
行为执行期间事件的路由遵循实体生命周期的轮廓:创建,修改和删除.在创建过程中,Apply方法会创建一个新实体(请记住,这是我们唯一允许更改状态的地方)并将其分配给字段,将其添加到列表,字典或自定义集合中.Apply方法中的修改通常涉及查找受影响的实体,或者将事件路由到实体,或者在使用事件数据应用更改的实体上具有专用内部方法.删除时,Apply方法执行查找并删除受影响的实体.注意这些Apply方法如何与再水化阶段混合以达到相同的状态.
现在,重要的是要理解可能存在影响实体但不"属于"任何特定实体的其他行为(可以说没有一对一的映射).这只是发生的事情,对一个或多个实体有副作用.正是这些让您欣赏实体设计灵活性的东西.
| 归档时间: |
|
| 查看次数: |
1934 次 |
| 最近记录: |