前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core快速入门(第3章:依赖注入)--学习笔记

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

作者头像
郑子铭
发布2021-01-13 10:42:35
3510
发布2021-01-13 10:42:35
举报
文章被收录于专栏:DotNet NB && CloudNative

课程链接: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产生了依赖

代码语言:javascript
复制
var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
2、显示依赖与隐式依赖

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

代码语言:javascript
复制
private CustomerContext _context;

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

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

代码语言:javascript
复制
var context = new CustomerContext(new DbContextOptions<CustomerContext>{});
3、依赖倒置原则

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

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

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

代码语言:javascript
复制
private ICustomerRepository _customerRepository;

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

任务18:控制反转

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

代码语言:javascript
复制
private ICustomerRepository _customerRepository;

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

任务19:单元测试

代码语言:javascript
复制
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

代码语言:javascript
复制
    /// <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接口中使用

代码语言:javascript
复制
    private IServiceCollection BuildCommonServices(
      out AggregateException hostingStartupErrors)
    {

      ......
      
      ServiceCollection services = new ServiceCollection();
      
      // new完之后添加一些初始化操作
      
      ......

      return (IServiceCollection) services;
    }

IStartup接口

代码语言:javascript
复制
namespace Microsoft.AspNetCore.Hosting
{
  public interface IStartup
  {
    IServiceProvider ConfigureServices(IServiceCollection services);

    void Configure(IApplicationBuilder app);// 配置管道
  }
}

第四步,webHost初始化方法Initialize

代码语言:javascript
复制
    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/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 任务16:介绍
  • 任务17:从UML角度来理解依赖
    • 1、什么是依赖
      • 2、显示依赖与隐式依赖
        • 3、依赖倒置原则
        • 任务18:控制反转
        • 任务19:单元测试
        • 任务20:DI初始化的源码解读
        • 任务21:依赖注入的使用
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档