(译)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 ...
随机推荐
- JavaScript--我发现,原来你是这样的JS(引用类型不简单,且听我娓娓道来)
一.介绍 没错,这是第五篇,到了引用类型,这次要分成两次博文了,太多内容了,这是前篇,篇幅很长也很多代码,主要讲引用类型和常用的引用类型,代码试验过的,老铁没毛病. 坚持看坚持写,不容易不容易,希望大 ...
- JqueryMobile基础之创建页面
首先简答介绍一下JQueryMobile吧,我觉得用一句话来讲就是可以 "写更少的代码,做更多的事情" : 它可以通过一个灵活及简单的方式来布局网页,且兼容所有移动设备.这也是我自 ...
- JAVA基础知识总结:三
一.Java语句的执行结构 1.顺序语句 按照顺序从上往下依次执行的语句,中间没有任何的判断和跳转 2.分支语句 根据不同的条件来产生不同的分支 if语句.switch语句 3.循环语句 重复执行某句 ...
- Sketch设计学习(一)
很膜拜那些既能写出一手好代码,并且还能够懂设计懂交互的人.公司基本上都对这两块工作 分工分职,但是我觉得作为一名移动开发者,懂点设计 是必备的. 国外的很多大牛们,感觉他们虐我们千百遍了. 我觉得写代 ...
- css3+div画大风车
今天已经礼拜三了,周天小颖家的佩佩就要结婚啦,小颖要去当伴娘了,哈哈哈哈哈哈,想想都觉得乐开了花,不过之前她给我说让我当她伴娘时,我说我要减肥,不然她那么瘦弱,我站旁边就感觉像一个圆滚滚的小皮球,小颖 ...
- 关于在Python下安装布隆过滤器(bloomfilter)的方法
由于在爬虫代码中需要实现信息的去重功能,所以需借助bloomfilter,在看完各种博客后发现没有安装,这就尴尬了,不会连门都找不到吧.那就安装呗,各种错误,查看官方文档:http://axiak.g ...
- c语言的,三个工具可以使编译器生成性能更佳的代码。
内联函数声明inline 函数有时可以非常短.短函数的每次调用可以用实现该函数功能的内联代码替代,以提高执行性能.意味着不需要给函数传递或返回一个值,要让编译器采用这种技术,可以把短函数指定为inli ...
- Ionic3 打包并签名Android-App
ionic cordova build android --prod --release 此时,在项目根目录中看下看到生成的apk文件:platforms\android\build\outputs\ ...
- 349B - Color the Fence
Color the Fence Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Su ...
- RPA(Robotic Process Automation)的概要介绍
最近因为公司业务的需要,开始关注RPA的内容,奈何国内相关的信息太少,只能硬着头皮啃英文了. 下面记录的内容作为学习笔记,有不对的地方请大家指教. 首先RPA(Robotic Process Auto ...