zoukankan      html  css  js  c++  java
  • 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) 。

  • 相关阅读:
    Eclipse快捷键大全,导包快捷键:ctrl+Shift+/【转】
    xml合并工具【原】
    解决win10无线无故断网,重启才恢复正常的情况【原】
    PL/SQL可以连oracle,但是jdbc连不上 【转】
    Java 编程下使用 Class.forName() 加载类【转】
    Http请求中Content-Type讲解以及在Spring MVC中的应用【转】
    activeMQ
    概念,包括对象,接口,类,方法
    javabean
    session
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/11273694.html
Copyright © 2011-2022 走看看