ASP.NET Core快速入門(第3章:依賴注入)

 

任務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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章