依赖注入模块依赖注册

时间:2015-11-07 13:51:23

标签: dependency-injection software-design

我尝试以模块化方式设计我的应用程序。我希望能够在任何给定的交换模块。

使用依赖注入模式可以让我做到这一点。但有些东西一直困扰着我。

在我遇到的大多数代码中,有一个地方将接口链接到所需的接口。例如在asp.net vnext中,它看起来像这样:

public void ConfigureServices(IServiceCollection services)
{            
    // business-layer
    services.AddTransient<IArticleRepository, ArticleRepository>();

    // data-layer
    services.AddTransient<IDataConnection, DataConnection>();
}

但我不喜欢只有一个地方可以进行注册。我宁愿让每个模块注册自己的接口/实现:

在我的业务层(模块)

public void ConfigureServices(IServiceCollection services)
{            
    // business-layer
    services.AddTransient<IArticleRepository, ArticleRepository>();           
}

在我的数据层(模块)

public void ConfigureServices(IServiceCollection services)
{            
    // data-layer
    services.AddTransient<IDataConnection, DataConnection>();           
}

有没有任何模式或最佳做法来做这种事情?我可以创建一些接口并在加载时完成此接口的所有实现,但我不确定这是否是最好的方法。

2 个答案:

答案 0 :(得分:2)

  

是否有任何模式或最佳做法来做这类事情?

是和否。有Facade pattern,您可以为不需要对API进行细粒度控制的客户端提供简化的API。 Facade模式并没有明确涉及依赖注入,但是如果这是一个有意义的事情,你总是可以提供默认的服务组合。我的文章DI Friendly Library中有更多详细信息。

也就是说,保持API开放非常重要,因此Facade只是您向客户提供的选项之一。如果您在库中预先构建对象图,并且不为客户端提供任何方法来规避该默认组合,则这样的库将是一个单片黑盒子。来自依赖注入的所有外部好处都将消失,因为客户端将无法替换或扩展服务。

请遵循DI Friendly Library文章中列出的准则,但请务必避免使用Conforming Container anti-pattern

答案 1 :(得分:0)

我想说配置你的DI的方式/地点在很大程度上取决于你的DI框架。一些框架允许您按模块进行配置,其他框架则需要一个全局配置。在后一种情况下,您可以手动委派给您的子模块(只需将IServiceCollection传递给子模块配置代码)。

关于最佳实践:我很少看到使用DI来实现多个生产实施。通常只有一个生产实现,而DI仅用于在没有样板的情况下将所有内容连接在一起。但是许多不同的实现(通常是模拟)通常在没有DI框架的情况下通过手动布线进行测试。如果这也是你的情况那么你的直觉是正确的:让DI框架扫描整个代码,采用默认/唯一的实现并将其作为依赖项注入将是很好的。如果您的DI框架提供了这项功能,那么您很幸运。如果没有,你必须自己实施