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?
我发现的设置Ninject模块的实用方法可以在下面找到。
概述
- 创建名为
DependencyResolution
的程序集 - 创建 Ninject 模块(您将在 WebAPI 项目中使用的模块)
- 在 WebAPI 项目中仅引用此
DependencyResolution
和域项目
在 NinjectWebCommon.cs
中启动/注册模块
详
- 创建项目应该很容易,例如,将 Ninject 添加为来自 NuGet 的引用。
- 向该项目添加新的类文件,以您要创建的模块命名,例如:
ServiceModule.cs
、RepositoryModule.cs
等。创建你的 Ninject 模块。有关这方面的详细说明,您可以参考我的回答。 - 在 WebAPI 项目中,添加对刚刚创建的
DependencyResolution
项目和域项目的引用。 -
在 WebAPI 项目的
NinjectWebCommon.cs
中将刚刚创建的模块初始化/注册为:private static void RegisterServices(IKernel kernel) { var modules = new List<INinjectModule> { new ServiceModule(), new RepositoryModule() }; kernel.Load(modules); }
我还将尝试解决与您的问题松散相关的另一个问题。我认为您当前的分层设置需要稍作更改。
您的图层的基本问题,也可能是我最大的问题是您混淆了域和存储库,因此紧密耦合,这显然是一个基础设施问题。
我建议将您的图层重新构建为:
- 域
- 服务业
- 基础设施(例如,存储库实现可以放在这里)
- 依赖关系解析
- 网络接口
不要忘记,您的域层不应该对存储库等基础设施细节有任何了解,否则您将将您的域与不需要的实现细节紧密耦合。
编辑:从评论中,我看到你对放置位置以及如何命名事物有一些担忧,这显然是编程中最困难的事情之一。
因此,我对消除这种困惑的想法是:
层:是类、方法等所属的逻辑分离或集合点。
每个层可以包含多个项目或程序集。因此,如果要将项目分类为层,可以在解决方案中创建名为"图层"的目录,并将各个项目放在这些目录中。这真的只是口中的味道问题,把它当作提示。
示例结构
- 解决方案根目录
- 核心目录
- 域
- 程序集:您拥有业务或域实体的域的根目录,以及您的域正在使用的所有接口。 域
- 服务程序集(也可能在域程序集中)
- 服务目录
- 应用程序服务程序集:例如,此程序集包含跨多个域实体或聚合等操作的服务或外观。
- 基础结构目录
- 存储库
- 程序集:这是实现 EF 存储库的位置
- 自定义日志记录/电子邮件/不属于域的任何其他程序集或实现。
- 依赖关系解析程序集:这是您的 NInject 模块和所有 IOC 容器相关接线的地方。
- 用户界面目录
- 网络接口程序集
- 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