DI container for 2 layers

本文关键字:layers for container DI | 更新日期: 2023-09-27 18:31:57

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

  • 域(存储库)层
  • 服务
  • 网络 API 应用程序核心

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

您能否告诉我,我应该在WebApi项目中使用DI容器(Ninject)来绑定IService<T>ServiceConcrete<T>,在服务项目中使用DI容器来绑定IRepository<T>RepositoryConcrete<T>

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

DI container for 2 layers

我发现的设置Ninject模块的实用方法可以在下面找到。

概述

  1. 创建名为 DependencyResolution 的程序集
  2. 创建 Ninject 模块(您将在 WebAPI 项目中使用的模块)
  3. 在 WebAPI 项目中仅引用此DependencyResolution和域项目
  4. NinjectWebCommon.cs中启动/注册模块

  1. 创建项目应该很容易,例如,将 Ninject 添加为来自 NuGet 的引用。
  2. 向该项目添加新的类文件,以您要创建的模块命名,例如:ServiceModule.csRepositoryModule.cs等。创建你的 Ninject 模块。有关这方面的详细说明,您可以参考我的回答。
  3. 在 WebAPI 项目中,添加对刚刚创建的DependencyResolution项目和域项目的引用。
  4. 在 WebAPI 项目的NinjectWebCommon.cs中将刚刚创建的模块初始化/注册为:

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

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

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

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

  • 服务业
  • 基础设施(例如,存储库实现可以放在这里)
  • 依赖关系解析
  • 网络接口

不要忘记,您的域层不应该对存储库基础设施细节有任何了解,否则您将将您的域与不需要的实现细节紧密耦合。

编辑:从评论中,我看到你对放置位置以及如何命名事物有一些担忧,这显然是编程中最困难的事情之一。

因此,我对消除这种困惑的想法是:

:是类、方法等所属的逻辑分离或集合点。

每个层可以包含多个项目或程序集。因此,如果要将项目分类为层,可以在解决方案中创建名为"图层"的目录,并将各个项目放在这些目录中。这真的只是口中的味道问题,把它当作提示。

示例结构

  1. 解决方案根目录
  2. 核心目录
    • 程序集:您拥有业务或域实体的域的根目录,以及您的域正在使用的所有接口。
    • 服务程序集(也可能在域程序集中)
  3. 服务目录
    • 应用程序服务程序集:例如,此程序集包含跨多个域实体或聚合等操作的服务或外观。
  4. 基础结构目录
      存储库
    • 程序集:这是实现 EF 存储库的位置
    • 自定义日志记录/电子邮件/不属于域的任何其他程序集或实现。
    • 依赖关系解析程序集:这是您的 NInject 模块和所有 IOC 容器相关接线的地方。
  5. 用户界面目录
    • 网络接口程序集
    • Asp.Net MVC 组件

总结

依赖关系解析项目引用了任何所需的程序集(接口的域,其实现的服务/基础结构),并将它们完全连接以供以后使用。

WebAPI 项目只需要添加引用域和依赖解析,这样您就可以在 WebAPI 方法/函数公共构造函数中请求接口,Ninject 将在幕后为您完成繁琐的工作。

请不要忘记,这只是我的一个简单快速的肮脏架构建议,不知道您的确切要求和用例。

如果我理解您的问题,那么您在配置存储库层时遇到了麻烦,因为您的配置代码位于应用程序层中,该层可能仅引用您的服务层(而服务层又引用了您的存储库层)。为了解决这个问题,我所做的是首先在模块中创建您的配置(这些配置可以存在于任何层上,但您必须引用 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