繁体   English   中英

具有存储库的域驱动设计中的对象创建策略

[英]Object creation strategy in domain driven design with repositories

我正在玩Domain Driven Development。 我使用的通用存储库实现定义如下:(这是作为Repository<T>

   public interface IRepository<T> where T : class, IEventSource, new()
    {
        T FindByKey(Guid key);
        IEnumerable<T> FindByQuery(Predicate<T> filter);
        IEnumerable<T> GetAll();
        T CreateObject();
    }

假设我有一个Order类,没有Customer参数就无法创建。 我正在使用CreateObject来设置具有顺序Guid生成器的实体的Key。

什么是最小化开发时间和耦合的解决方案?

  • 目前我有一个无参数构造函数,并调用一些Initialize(Customer)方法。
  • 我可以创建一个ICustomerRepository,但这意味着每个实体有很多额外的开发时间。
  • 我也可以修改CreateObject来获取params object[] args ,但这在编译时不是类型安全的。
  • 我可以删除CreateObject并使用构造函数来创建对象,但这意味着我需要在实例化对象的任何地方访问Guid生成算法,从而增加耦合。
  • 在实体的基类中,我可以在构造函数中设置键,减少耦合,但需要对算法进行一些静态引用。

更新

我按照sll的回答实施了这个策略。 现在,存储库的新签名是:

public interface IRepository<T> where T : class, IEventSource
{
    T FindByKey(Guid key);
    IEnumerable<T> FindByQuery(Func<T, bool> predicate);
    IEnumerable<T> GetAll();
    T CreateObject();
    T CreateObject(IConstructorParameters parameters);
}

无参数CreateObject通过尝试调用无参数构造函数(使用IL Emit实现性能)来创建实例。

第二个CreateObject尝试创建一个方法来调用构造函数,其中IConstructorParameters上的IConstructorParameters与Entity对象上的构造函数匹配。

执行:

private Dictionary<Type, Func<IConstructorParameters, T>> _constructionMethods 
    = new Dictionary<Type, Func<IConstructorParameters, T>>();
public T CreateObject(IConstructorParameters args)
{
    T newObject;
    if (args == null)
    {
        args = ConstructorParameters.Empty;
    }
        Type paramType = args.GetType();
        Func<IConstructorParameters, T> constructor;

        if (!_constructionMethods.TryGetValue(paramType, out constructor))
        {
            //Emit IL to create a Func<IConstructorParameters,T>
            constructor = CreateConstructor(paramType);
            _constructionMethods.Add(paramType, constructor);
        }

        newObject = constructor(args);

    newObject.Key = _guidCreator.Generate();
    return newObject;
}

一些观点作为建议,我会做如下。

  • 保持IRepository的通用性,并且还创建包含合同的特定接口,仅包含与实体相关的内容,ICustomerRepository作为示例。
  • 将guid生成删除到服务类,因为此任务与基础结构而非域相关。

如果您不想实现IOrderRepository - 您可以通过IConstructionParameters类的接口抽象CreateObject()方法参数,然后为每个实体实现具体参数,如OrderConstructionParameters

这种方法也称为参数对象设计模式,其设计原理 - 更多解耦系统设计。

public interface IRepository<T> 
{
   T CreateObject(IConstructionParameters parameters);     
} 

public sealed class OrderConstructionParameters : IConstructionParameters
{
    public Customer Customer
    { 
       get; 
       private set; 
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM