2层DI容器

DI container for 2 layers

我正在尝试使用像 Ninject 这样的 IoC 来设计 WebApi 应用程序。我有以下层(3 个项目):

Repository 层有接口 IRepository<T> 和它的一些实现。并且在服务中还存在具有两种不同实现的接口 IService<T>

请问我是否应该在 WebApi 项目中使用 DI 容器 (Ninject) 来绑定 IService<T>ServiceConcrete<T> 以及在 Service 项目中使用 DI 容器来绑定 IRepository<T>RepositoryConcrete<T>?

或者我应该在 WebAppi 项目中只使用一个 DI?

如果我理解你的问题,你在配置存储库层时遇到了问题,因为你的配置代码在你的应用程序层中,它可能只引用你的服务层(它又引用你的存储库层)。为了解决这个问题,我所做的是首先在模块中创建您的配置(这些可以存在于任何层上,但您必须参考 Ninject)

对于您的回购层:

public class RepoNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyRepo>().To<MyRepo>();
    }
}

在您的服务层创建一个类似的模块:

public class ServiceNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyService>().To<MyServce>();
    }
}

然后,在你的应用层,你可以动态加载模块(这就是NinjectWebCommon.cs的样子):

private static void RegisterServices(IKernel kernel)
{
    kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
}

有关模块的更多信息:https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel

下面是我发现的设置 Ninject 模块的实用方法。

概览

  1. 创建一个名为 DependencyResolution
  2. 的程序集
  3. 创建 Ninject 模块(您将在 WebAPI 项目中使用)
  4. 只有这个 DependencyResolution 和您的 WebAPI 项目中引用的域项目
  5. Initalize/register 你的模块在 NinjectWebCommon.cs

详情

  1. 应该像 create a project 一样简单,例如从 NuGet 添加 Ninject 作为参考。
  2. 向此项目添加新的 class 文件,以您要创建的模块命名,例如:ServiceModule.csRepositoryModule.cs 等。 在此创建您的Ninject module(s). For detailed instructions on this you can refer my
  3. 在您的 WebAPI 项目中,您添加对刚刚创建的 DependencyResolution 项目和您的域项目的引用。
  4. Initializing/registering 您刚刚在 WebAPI 项目的 NinjectWebCommon.cs 中创建的模块为:

    private static void RegisterServices(IKernel kernel)
    {
        var modules = new List<INinjectModule>
        {
            new ServiceModule(),
            new RepositoryModule()
        };
    
        kernel.Load(modules);
    }  
    

我还将尝试解决另一个与您的问题松散相关的问题。我认为您当前的分层设置需要稍微更改一下。

你的层的基本问题,可能也是我最大的问题是,你混淆了域和存储库,因此紧密耦合,这显然是一个基础设施问题

我建议将您的图层重新架构为:

  • 服务
  • 基础架构(例如,存储库实现可以放在此处)
  • 依赖关系解析
  • WebAPI

不要忘记你的域层应该了解基础设施细节,比如存储库,否则你将紧密耦合您的域包含不需要的实施细节。

编辑: 从评论中我看到您对放置的位置和如何命名有些担忧,这是 obviously 编程中最困难的事情之一.

所以我对消除这种困惑的想法是:

Layer:是classes、方法等的逻辑分离或集合点。

每一层可以包含多个项目或程序集。因此,如果您想将项目分类到层中,您可以在以层命名的解决方案中创建 directories,并将各个项目放置在这些目录中。真的只是口口相传,小费而已。

示例结构

  1. 解决方案根
  2. 核心目录
    • 域组件:您拥有业务或域实体以及您的域正在使用的所有接口的域的根。
    • 域服务程序集(也可以在域程序集中)
  3. 服务目录
    • 应用服务程序集:例如,这个程序集包含跨多个域实体或聚合等操作的服务或外观。)
  4. 基础结构目录
    • 存储库程序集:这是您实现 EF 存储库的地方
    • 自定义 logging/email/whatever else 不属于域的程序集或实现。
    • DependencyResolution 程序集:这是您的 NInject 模块和所有 IOC 容器相关布线的地方。
  5. UI目录
    • WebAPI 程序集
    • Asp.Net MVC 程序集

总结

Dependency Resolution 项目引用了任何需要的程序集(Domain 用于接口,Services/Infrastructure 用于它们的实现)并将它们连接在一起供以后使用。

WebAPI 项目只需要添加引用域和依赖项解析,这样您就可以在 WebAPI methods/functions public 构造函数中请求您的接口,Ninject 就可以了你在幕后的肮脏工作。

请不要忘记,这只是我在不了解您的确切要求和用例的情况下提出的一个简单快速的肮脏架构建议。