(译)ABP之依赖注入
原文地址:https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection
- 什么是依赖注入
- 传统方式的问题
- 解决方案
- 构造函数注入
- 属性注入
- 依赖注入框架
- ABP依赖注入基础设施
- 注册依赖项
- 常用注册
- 帮助接口
- 自定义/直接注册
- 使用IocManager
- 解析
- 构造函数&属性注入
- IIocResolver, IIocManager and IScopedIocResolver
- 附加部分
- IShouldInitialize 接口
- ASP.NET MVC & ASP.NET Web API 集成
- ASP.NET Core 集成
- 最后备注
什么是依赖注入
传统方式的问题
public class PersonAppService
{
private IPersonRepository _personRepository; public PersonAppService()
{
_personRepository = new PersonRepository();
} public void CreatePerson(string name, int age)
{
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
}
}
- PersonAppService在CreatePerson方法里使用了IPersonRepository的引用,所以这个方法依赖于IPersonRepository,而不是依赖于PersonRepository,但是,在PersonAppService的构造函数中依然依赖于PersonRepository。组件应该依赖于接口而不是实现类。这就是依赖反转原则。
- 如果PersonAppService创建PersonRepository本身,这样就变成了依赖IPersonRepository接口具体的实现类了,同时使得它不能用IPersonRepository接口的其它实现类,这样,将接口与实现类分离就毫无意义了。强依赖关系使得代码基础紧密耦合,且可重用性较低。
- 我们在以后可能需要改变PersonRepository的创建,比如说,我们可能想把它创建成一个单例(单一共享一个实例,而不是每次用时都创建一个对象),或者我们可能想创建多个IPersonRepository接口的实现类,而我们是根据条件来创建其中某个实现类的实例。在这种情况下,我们就得修改所有依赖于IPersonRepository接口的类。
- 有了这样的依赖关系,我们是很难(或者不可能)对PersonAppService进行单元测试。
public class PersonAppService
{
private IPersonRepository _personRepository; public PersonAppService()
{
_personRepository = PersonRepositoryFactory.Create();
} public void CreatePerson(string name, int age)
{
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
}
}
- 这次,PersonAppService 依赖于PersonRepositoryFactory ,这个相当来说还可以接受,但是这样还是一种强依赖关系。
- 为每一个repository 或它的依赖类写一个工厂类或方法是很乏味的。
- 这样可测试性还是不好,因为很难让PersonAppService 去使用一些模拟实现IPersonRepository的对象。
解决方案
构造函数注入模式
public class PersonAppService
{
private IPersonRepository _personRepository; public PersonAppService(IPersonRepository personRepository)
{
_personRepository = personRepository;
} public void CreatePerson(string name, int age)
{
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
}
}
var repository = new PersonRepository();
var personService = new PersonAppService(repository);
personService.CreatePerson("Yunus Emre", );
- 创建一个PersonAppService 对象变得更难了。试想一下,如果PersonAppService 依赖于4个类,那我们就必须创建这4个依赖类的对象,并把它们传递给PersonAppService 的构造函数。
- 依赖类可能也有它们自己的依赖类(这里,PersonRepository可能还依赖其它的类),因此,我们必须创建所有PersonAppService 所依赖的对象,以及这些依赖对象所依赖类的对象,如此等等。这样,我们甚至连一个对象都创建不了了,因为这依赖关系它复杂了。
属性注入模式
public class PersonAppService
{
public ILogger Logger { get; set; } private IPersonRepository _personRepository; public PersonAppService(IPersonRepository personRepository)
{
_personRepository = personRepository;
Logger = NullLogger.Instance;
} public void CreatePerson(string name, int age)
{
Logger.Debug("Inserting a new person to database with name = " + name);
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
Logger.Debug("Successfully inserted!");
}
}
var personService = new PersonAppService(new PersonRepository());
personService.Logger = new Log4NetLogger();
personService.CreatePerson("Yunus Emre", );
依赖注入框架
var container = new WindsorContainer(); container.Register(
Component.For<IPersonRepository>().ImplementedBy<PersonRepository>().LifestyleTransient(),
Component.For<IPersonAppService>().ImplementedBy<PersonAppService>().LifestyleTransient()
); var personService = container.Resolve<IPersonAppService>();
personService.CreatePerson("Yunus Emre", );
ABP依赖注入基础设施层
注册依赖项
常规注册
public interface IPersonAppService : IApplicationService
{
//...
} public class PersonAppService : IPersonAppService
{
//...
}
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
帮助接口
public interface IPersonManager
{
//...
} public class MyPersonManager : IPersonManager, ISingletonDependency
{
//...
}
自定义/直接注册
使用IocManager
IocManager.Register<IMyService, MyService>(DependencyLifeStyle.Transient);
使用Castle Windsor API
IocManager.IocContainer.Register(Classes.FromThisAssembly().BasedOn<IMySpecialInterface>().LifestylePerThread().WithServiceSelf());
更多信息,可以参考Windsor文档
解析
构造函数&属性注入
public class PersonAppService
{
public ILogger Logger { get; set; } private IPersonRepository _personRepository; public PersonAppService(IPersonRepository personRepository)
{
_personRepository = personRepository;
Logger = NullLogger.Instance;
} public void CreatePerson(string name, int age)
{
Logger.Debug("Inserting a new person to database with name = " + name);
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
Logger.Debug("Successfully inserted!");
}
}
IIocResolver, IIocManager and IScopedIocResolver
public class MySampleClass : ITransientDependency
{
private readonly IIocResolver _iocResolver; public MySampleClass(IIocResolver iocResolver)
{
_iocResolver = iocResolver;
} public void DoIt()
{
//Resolving, using and releasing manually
var personService1 = _iocResolver.Resolve<PersonAppService>();
personService1.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
_iocResolver.Release(personService1); //Resolving and using in a safe way
using (var personService2 = _iocResolver.ResolveAsDisposable<PersonAppService>())
{
personService2.Object.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
}
}
}
using (var scope = _iocResolver.CreateScope())
{
var simpleObj1 = scope.Resolve<SimpleService1>();
var simpleObj2 = scope.Resolve<SimpleService2>();
//...
}
附加部分
IShouldInitialize 接口
ASP.NET MVC & ASP.NET Web API 集成
ASP.NET Core集成
最后备注
(译)ABP之依赖注入的更多相关文章
- ABP的依赖注入
目录 说说ABP的依赖注入 代码追踪 说说ABP的依赖注入 上篇abp运行机制分析分析了ABP在启动时,都做了那些事:这篇我们来说说ABP的最核心的一部分:依赖注入(DependencyInjecti ...
- ABP框架 - 依赖注入
文档目录 本节内容: 什么是依赖注入 传统方式的问题 解决方案 构造器注入模式 属性注入模式 依赖注入框架 ABP 依赖注入基础 注册依赖 约定注入 辅助接口 自定义/直接 注册 使用IocManag ...
- ABP之依赖注入
写在开头 ABP开源项目最近有点小火,还开展了线下活动.本着学习DDD的心态与学习开源代码的的好奇,我也看了一遍ABP源码,在此将自己学习ABP的一些心得记录下来. 作为核心的IoC 作为一种解耦的方 ...
- [译] 关于 Angular 依赖注入你需要知道的
如果你之前没有深入了解 Angular 依赖注入系统,那你现在可能认为 Angular 程序内的根注入器包含所有合并的服务提供商,每一个组件都有它自己的注入器,延迟加载模块有它自己的注入器. 但是,仅 ...
- Asp.Net Core 3.1 Api 集成Abp项目依赖注入
Abp 框架 地址https://aspnetboilerplate.com/ 我们下面来看如何在自己的项目中集成abp的功能 我们新建core 3.1 API项目和一个core类库 然后 两个项目都 ...
- ABP(现代ASP.NET样板开发框架)系列之6、ABP依赖注入
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
- ABP源码分析六:依赖注入的实现
ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...
- ABP理论学习之依赖注入
返回总目录 本篇目录 什么是依赖注入 传统方式产生的问题 解决办法 依赖注入框架 ABP中的依赖注入基础设施 注册 解析 其他 ASP.NET MVC和ASP.NET Web API集成 最后提示 什 ...
- ABP依赖注入
ABP依赖注入 点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之6.ABP依赖注入 ABP是“ASP.NET Boilerplate Project (ASP.N ...
随机推荐
- Java基础总结--面向对象2
1.存在相关的多个方法就封装在一个类中,方法没调用到特有数据,需要静态化2.假如一个类所有方法都是静态方法,为了保证不被其他创建对象,可以将该类的构造方法私有化3.文档注释javadoc-按照规定注释 ...
- oracle实用基础
Oracle修改字段名 alter table 表名 rename column 旧字段名 to 新字段名例子:alter table T_STUDENT rename column NAME to ...
- 数据分析与展示——NumPy库入门
这是我学习北京理工大学嵩天老师的<Python数据分析与展示>课程的笔记.嵩老师的课程重点突出.层次分明,在这里特别感谢嵩老师的精彩讲解. NumPy库入门 数据的维度 维度是一组数据的组 ...
- x86-64栈帧中的“红色区域” red zone of stack frame on x86-64
前几天看System V AMD64 ABI标准的时候发现栈帧的顶部后面有一块"red zone",在学cs:app3e/深入理解操作系统的时候并没有遇到这个,总结一下. 引用标准 ...
- Tinyhttpd阅读笔记
1.简介 tinyhttpd是一个开源的超轻量型Http Server,阅读其源码,可以对http协议,微型服务器有进一步的了解. 源码链接: 参考博客:tinyhttpd源码分析 2.笔记 ---- ...
- [Bayesian] “我是bayesian我怕谁”系列 - Variational Autoencoders
本是neural network的内容,但偏偏有个variational打头,那就聊聊.涉及的内容可能比较杂,但终归会 end with VAE. 各个概念的详细解释请点击推荐的链接,本文只是重在理清 ...
- 详细图解window环境mongodb下载、安装、配置与使用
到官网下载最新版面mongodb安装包,(32位版本的已经取消了,只有64位的) 官网地址: https://www.mongodb.com/download-center#community 下载完 ...
- robotframework自动化系列:随机下拉框
robotframework自动化系列:随机下拉框 随着项目自动化不断推进,在下拉框定位的时候出现些问题,每次下拉框选择都是相同的下拉选项,如果想每次选择的选项不一样,该如何实现呢,查找了很多资料,没 ...
- js数组元素的添加和删除
简单测试例子: var arr = new Array(); arr[0] = "aaa"; arr[1] = "bbb"; arr[2] = "cc ...
- NoSQL:linux操作memcached
缓存数据库 一 NoSQL简介 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系 ...