点击蓝字关注我们
课程链接:/course/explore
良心课程,大家一起来学习哈!
任务16:介绍
1、依赖注入概念详解
从UML和软件建模来理解
从单元测试来理解
2、 Core 源码解析
任务17:从UML角度来理解依赖
1、什么是依赖
当一个类A完成某个任务需要另一个类B来帮助时,A就对B产生了依赖
例如CustomerController需要对customer进行新增或查找时用到EF,则对EF的Context产生了依赖
var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
2、显示依赖与隐式依赖
显示依赖:把一个类用到的所有外部组件放到一个类最上面,在构造函数里面初始化
public CustomerController() { _context = new CustomerContext(new DbContextOptions<CustomerContext>{}); }private CustomerContext _context;
隐式依赖:需要用到的地方再初始化,不推荐
var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
3、依赖倒置原则
依赖高层业务,不依赖低层业务的具体实现,而依赖于具体的抽象
CustomerController是高层业务的一个组件,依赖于CustomerContext是一个低层数据库的实现,如果现在需要把EF换成一个内存的实现或者mysql,需要修改CustomerController类,风险很大,所以应该依赖于低层业务的抽象
把低层业务方法抽象,比如查找,新增,抽象出一个接口,当不需要使用EF的时候,使用内存的实现替换
public CustomerController() { _customerRepository = new EfCustomerRepository( new CustomerContext(new DbContextOptions<CustomerContext>{})); }private ICustomerRepository _customerRepository;
任务18:控制反转
实现依赖注入的方式不由自己决定,而是交给一个IOC容器,需要什么由容器传入,比如生产环境需要使用EF,则由容器传入一个EfCustomerRepository,而测试环境需要使用内存级别的,则传入一个MemoryCustomerRepository
public CustomerController(ICustomerRepository customerRepository) { _customerRepository = customerRepository; }private ICustomerRepository _customerRepository;
任务19:单元测试
var controller = new CustomerController(repository);// 通过外部控制Controller里面的依赖 var customer = new Model.Customer() { FirstName = "Mingson", LastName = "Zheng", Phone = "123456789", }; var result = controller.Add(customer); Assert.IsType<OkResult>(result);// 正确结果 var resultBad = controller.Add(customer); Assert.IsType<BadRequestObjectResult>(resultBad);// 错误结果var repository = new Data.MemoryCustomerRepository();
通过单元测试可以得知修改Bug过程中是否误删代码,导致原来通过的测试现在无法通过。
任务20:DI初始化的源码解读
Microsoft.AspNetCore.Hosting.WebHostBuilder
/// Builds the required services and an <see cref="T:Microsoft.AspNetCore.Hosting.IWebHost" /> which hosts a web application. /// </summary> public IWebHost Build() { ...... // 第一步,build IServiceCollection serviceCollection1 = this.BuildCommonServices(out hostingStartupErrors); // 第二步,获取ServiceCollection,ServiceProvider IServiceCollection serviceCollection2 = serviceCollection1.Clone(); IServiceProvider providerFromFactory = GetProviderFromFactory(serviceCollection1); ...... // 第三步,new一个WebHost,传入ServiceCollection,ServiceProvider WebHost webHost = new WebHost(serviceCollection2, providerFromFactory, this._options, this._config, hostingStartupErrors); ...... // 第四步,webHost初始化方法Initialize webHost.Initialize(); ...... }/// <summary>
第一步BuildCommonServices中new一个ServiceCollection就是在startup接口中使用
out AggregateException hostingStartupErrors) { ...... ServiceCollection services = new ServiceCollection(); // new完之后添加一些初始化操作 ...... return (IServiceCollection) services; }private IServiceCollection BuildCommonServices(
IStartup接口
{ public interface IStartup { IServiceProvider ConfigureServices(IServiceCollection services); void Configure(IApplicationBuilder app);// 配置管道 } }namespace Microsoft.AspNetCore.Hosting
第四步,webHost初始化方法Initialize
{ ...... this.EnsureApplicationServices(); ...... } private void EnsureApplicationServices() { ...... this.EnsureStartup(); this._applicationServices = this._startup.ConfigureServices(this._applicationServiceCollection); } private void EnsureStartup() { if (this._startup != null) return; this._startup = this._hostingServiceProvider.GetService<IStartup>(); if (this._startup == null) throw new InvalidOperationException(string.Format("No startup configured. Please specify startup via WebHostBuilder.UseStartup, WebHostBuilder.Configure, injecting {0} or specifying the startup assembly via {1} in the web host configuration.", (object) "IStartup", (object) "StartupAssemblyKey")); }public void Initialize()
任务21:依赖注入的使用
了解 Core 依赖注入,看这篇就够了:
//11/06/di-in-aspnetcore/
点“在看”给我一朵小黄花