c# - 良好的设计 DDD 和 IoC,如何将 IRepository 注入(inject)模型

标签 c# domain-driven-design inversion-of-control

我有一个复杂的实体 (Message),它有一个相当庞大的构造函数(13 个参数),其中一些参数又是实体(Verb)。

有很多事情我需要另一个实体的存储库(例如,对于某些默认值)。

什么是使用 IoC 并保持代码清洁的好方法/最佳实践?

简化的代码(我将默认动词列表作为由静态构造函数亲自构造的静态对象,这是最简单的例子,如果我的 Message 实体需要某种 IRepositry)。

private static IVerbRepository verbRepository;

static Message()
{
    using (IKernel kernel = new StandardKernel())
    {
        verbRepository = kernel.Get<IVerbRepository>();
    }
}

public Message(int id, string precis,
    DateTime created, DateTime validTo,
    PriorityType priority, Source source, SID createdBy,
    string content = null, string helpText = null,
    DateTime? validFrom = null, bool emailOnExpiry = false,
    IEnumerable<SID> targetUsers = null,
    IOrderedEnumerable<MessageVerb> verbs = null) : base(id)
{
    Verbs = verbs ??
            new List<MessageVerb>
            {
                new MessageVerb(
                verbRepository.GetByName("Acknowledge"), true,
                string.Empty)
            }.OrderBy(x => x.IsDefault);

    Precis = precis;
    Created = created;
    ValidTo = validTo;
    Priority = priority;
    Source = source;
    CreatedBy = createdBy;
    Content = content;
    HelpText = helpText;
    ValidFrom = validFrom;
    EmailOnExpiry = emailOnExpiry;
    TargetUsers = targetUsers;
}

通常的做法似乎是向构造函数添加一个额外的参数。我不明白这怎么更好?这意味着每次您想要创建消息时,都需要编写代码来检索存储库。假设您将其包装在一个工厂中,允许(逻辑上如果不是实际上)有不同的消息实体存储库是没有意义的吗?

编辑 1

基于第一个解决方案,代码会像这样,

public Message(IVerbRepository verbRepository ...) {  }

在同一个域程序集的其他地方

public MessageService
{
    private IVerbRepository VerbRepository {get; set;}
    public static IOrderedEnumerable<MessageVerb> DefaultVerb {get;}
}

在我的 DDD 之外更高(假设我的网络服务接受消息的创建)

public class MessageWebService
{
    private static IVerbRepository _verbRepository;

    public void AddMessage(some parameters)
    {
        var message = new Message(_verbRepository, ...);
    }
}

最佳答案

IoC 有两种类型:Service Locator,您正在使用,Dependency Injection,您正在询问。

截至目前,Service Locator 被认为是一种反模式,因为它引入了隐式依赖项(您无法通过查看类的公共(public)接口(interface)来弄清楚的依赖项)并使测试更加困难。

另一方面,依赖注入(inject)没有这些问题,但在类声明中往往更加冗长。

现在,关于你的问题。

I don't get how this is better?

这是明确的。你可以看到你的类(class)依赖于这个或那个服务。顺便说一句,你的类没有,它只使用动词库来定位默认动词(可以很容易地移出类)。

Assumning you wrap this around in a Factory, it doesn't make sense to allow (logically if not actually) have different repositories for message entites?

当您想到测试时,它确实如此。您应该能够轻松地用可测试的实现( stub )替换您的 CUT 所依赖的任何服务。

关于c# - 良好的设计 DDD 和 IoC,如何将 IRepository 注入(inject)模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12158408/

相关文章:

c# - 在 Web 应用程序中在哪里以及如何使用拦截器?

java - java IoC框架如何保证线程安全?

c# - 为什么配置 NetworkStream 会断开客户端

entity - 值对象可以在没有实体的情况下存在吗?

c# - 使用数据库中的Reverse-LIKE进行选择

domain-driven-design - DDD-强制具有小的聚合根的不变量

java - 在域驱动的设计中,为什么要使用“聚合”对象?在设计聚合时将应用哪些关键原则?

.net - 使用 IoC 的开源项目

c# - 获取上传的 blob 的 URI?

c# - c#捕获鼠标点击事件