使用计算出的聚合ID的事件采购,我是否太聪明了?

时间:2014-07-21 21:27:28

标签: domain-driven-design cqrs event-sourcing

场景: 我有一个现有的UI,它不是非常关注有界的上下文,我有一些屏幕需要执行多个BC中的命令。我有想法根据聚合根ID(值对象)的值和聚合的类型来计算聚合ID(GUID)。我有一个事件表(SQL Server),其中存储了表示同一业务对象的多个聚合类型,并具有相同的值 - 对象ID(例如,PersonId)。

聚合根ID对象:

[Serializable]
public class PersonId : IEquatable<PersonId>
{
    public PersonId(string id)
    {
        Id = id;
    }

    public string Id { get; private set; }

    public bool Equals(PersonId other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return string.Equals(Id, other.Id);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != GetType()) return false;
        return Equals((PersonId) obj);
    }

    public override int GetHashCode()
    {
        return (Id != null ? Id.GetHashCode() : 0);
    }
}

计算聚合ID的扩展方法:

public static class AggregateIdExtensions
{
    public static Guid ToAggregateId(this object id, Type aggregateType)
    {
        var combinedIdentifiers = new Tuple<Type, object>(aggregateType, id);

        var md5 = MD5.Create();
        var bytes = ObjectToByteArray(combinedIdentifiers);
        var hash = md5.ComputeHash(bytes);

        return new Guid(hash);
    }

    private static byte[] ObjectToByteArray(Object obj)
    {
        if (obj == null)
            return null;
        var bf = new BinaryFormatter();
        var ms = new MemoryStream();
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }
}

用法:

var aggregateId = new PersonId("personId")
  .ToAggregateId(typeof (BoundedContextNumberOne.Person));

这里的目标是能够从UI执行命令而无需在读取的模型中携带来自多个BC的GUID聚合ID(我甚至不确定我能做到),或者强迫我携带额外的读取DB中的模型表以存储aggregate-root-id-to-aggregate-id关系,并在命令处理程序中强制执行其他查询。

这个解决方案“太过分了吗”?是否有更好的方法提出建议?

我也不确定如何计算使用不同类型/值生成相同GUID的聚合ID冲突的可能性。

0 个答案:

没有答案