• ASP.NET Core快速入门(第3章:依赖注入)--学习笔记


    课程链接:http://video.jessetalk.cn/course/explore

    良心课程,大家一起来学习哈!

    任务16:介绍

    1、依赖注入概念详解

    • 从UML和软件建模来理解
    • 从单元测试来理解

    2、ASP.NET Core 源码解析

    任务17:从UML角度来理解依赖

    1、什么是依赖

    当一个类A完成某个任务需要另一个类B来帮助时,A就对B产生了依赖

    例如CustomerController需要对customer进行新增或查找时用到EF,则对EF的Context产生了依赖

    var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
    

    2、显示依赖与隐式依赖

    显示依赖:把一个类用到的所有外部组件放到一个类最上面,在构造函数里面初始化

    private CustomerContext _context;
    
    public CustomerController()
    {
        _context = new CustomerContext(new DbContextOptions<CustomerContext>{});
    }
    

    隐式依赖:需要用到的地方再初始化,不推荐

    var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
    

    3、依赖倒置原则

    依赖高层业务,不依赖低层业务的具体实现,而依赖于具体的抽象

    CustomerController是高层业务的一个组件,依赖于CustomerContext是一个低层数据库的实现,如果现在需要把EF换成一个内存的实现或者mysql,需要修改CustomerController类,风险很大,所以应该依赖于低层业务的抽象

    把低层业务方法抽象,比如查找,新增,抽象出一个接口,当不需要使用EF的时候,使用内存的实现替换

    private ICustomerRepository _customerRepository;
    
    public CustomerController()
    {
        _customerRepository = new EfCustomerRepository(
            new CustomerContext(new DbContextOptions<CustomerContext>{}));
    }
    

    任务18:控制反转

    实现依赖注入的方式不由自己决定,而是交给一个IOC容器,需要什么由容器传入,比如生产环境需要使用EF,则由容器传入一个EfCustomerRepository,而测试环境需要使用内存级别的,则传入一个MemoryCustomerRepository

    private ICustomerRepository _customerRepository;
    
    public CustomerController(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }
    

    任务19:单元测试

    var repository = new Data.MemoryCustomerRepository();
    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);// 错误结果
    

    通过单元测试可以得知修改Bug过程中是否误删代码,导致原来通过的测试现在无法通过。

    任务20:DI初始化的源码解读

    Microsoft.AspNetCore.Hosting.WebHostBuilder

        /// <summary>
        /// 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();
            
            ......
    
        }
    

    第一步BuildCommonServices中new一个ServiceCollection就是在startup接口中使用

        private IServiceCollection BuildCommonServices(
          out AggregateException hostingStartupErrors)
        {
    
          ......
          
          ServiceCollection services = new ServiceCollection();
          
          // new完之后添加一些初始化操作
          
          ......
    
          return (IServiceCollection) services;
        }
    

    IStartup接口

    namespace Microsoft.AspNetCore.Hosting
    {
      public interface IStartup
      {
        IServiceProvider ConfigureServices(IServiceCollection services);
    
        void Configure(IApplicationBuilder app);// 配置管道
      }
    }
    

    第四步,webHost初始化方法Initialize

        public void 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"));
        }
    

    任务21:依赖注入的使用

    了解ASP.NET Core 依赖注入,看这篇就够了:

    http://www.jessetalk.cn/2017/11/06/di-in-aspnetcore/

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/11273694.html
Copyright © 2020-2023  润新知