.Net Core 3.1瀏覽器后端服務(四) 你眼中的依賴注入與我相同嗎?


一、前言

DI—Dependency Injection 依賴注入

IoC—Inversion of Control 控制反轉

近幾年這依賴注入、 控制反轉已成為軟件開發中不可或缺的一部分,那么該怎么理解這兩個概念呢?

在閱讀開始之前,大腦中先閃現幾個問號???

 

二、依賴注入

既然概念叫依賴注入,那首先分析一下什么是”依賴“?

依賴:是指一種特定的需求狀態,在面向對象的軟件開發過程中可以理解為對象A對另一對象B的一種引用關系。

下面以殺手刺殺舉例說明依賴的關系:

殺手需要一把槍來執行刺殺計划,這里從殺手的角度來看,對槍存在一種依賴關系,沒有槍就不能成功刺殺。代碼中表示如下:

public class Killer
{
    Gun gun = new Gun();
}

殺手只是需要一把槍,至於槍是如何生產的,殺手並不關心,我們改寫下代碼如下:

public class Killer
{
    private Gun _gun;
    public Killer(Gun gun)
    {
        _gun = gun;
    }
}

接着我們在Main方法中看下:

Killer的構造方法中需要Gun,我需要你。。。,即是我(Killer)對你(Gun)有所依賴,這就是依賴。

那什么是依賴注入呢?既然殺手需要一把槍,那么Main方法就提供一個Gun對象並賦予給Killer,代碼如下:

public class Program
{
    static void Main(string[] args)
    {
        Gun gun = new Gun();
        Killer killer = new Killer(gun);
    }
}

在我看來Main方法賦予給殺手gun對象的”過程“,即把你所需要的賦給你的”過程“這就是依賴注入。

了解了什么是依賴注入?那它有什么好處呢?亦或者說依賴注入的目的是什么?

在網上查找依賴注入概念時,控制反轉往往與其同時出現。那么好,我們先來看看控制反轉

三、控制反轉

既然叫控制反轉,那一定存在正向的了,那么什么算是正向的呢?

還是以殺手為例,

public Killer()
{
    Gun gun = new Gun();//創造一把槍
}

殺手自己創造一把槍,也就是自動去new即是正向

知道了正向,那么反向就不難理解了,殺手本身不去new,被動獲取即是反向。那何來控制一說呢?

好我們繼續看,先正向看,殺手創造一把槍(獲取槍消耗時間,存在風險,可能錯過最佳行刺時間)然后去刺殺,刺殺完成后還要銷毀槍(銷毀槍消耗時間,這個時間可能被抓,風險太大)。

public Killer()
{
    Gun gun = new Gun();//創造一把槍
    gun.Kill();//去行刺
    gun.Dispose();//銷毀槍
 }

既然創造槍和銷毀槍都有風險,和不將這兩部分交給其他人去做?下面反向來了

殺手在整個刺殺行動中,首先會有專人給殺手槍(這個過程就是依賴注入),殺手完成刺殺行動后,會有專人進行槍的善后處理。

即把槍除了刺殺之外的整個槍的使用過程控制權完全交給第三方。

 

總結一下:這里的使用過程即可理解為對象(槍)的生命周期,第三方即是容器。容器接管了對象的創建、銷毀的控制權。容器通過查找相關依賴動態的將對象(槍)注入給需求方(殺手)。

這種自身並不負責依賴對象的創建及銷毀。由容器來管理控制的思想稱之為控制反轉

 

這里可以回答上面遺留的問題,依賴注入的目的是什么?目的是實現控制反轉。

四、.net core中使用依賴注入

了解了依賴注入和控制反轉后,來看看.net core中在哪里進行的依賴注入,接下來回歸我們的項目

1、.net core自身的IOC容器

NET Core自身集成了一個輕量級的IOC容器,只要在Startup.cs的ConfigureServices方法中進行配置即可,如之前配置的用戶信息服務

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IUserInfoRepository, UserInfoRepository>();
    services.AddScoped<IUserInfoServices, UserInfoServices>();
}

這里需要注意一點,配置注入的生命周期。有三種注入的生命周期

AddSingleton 單一實例對象整個程序運行期間都是相同的(相當於單例模式,例如:全局配置信息,統計在線人數)

AddScoped 對每次請求而言對象是相同的,但在請求之間不同(例如:獲取用戶信息,每個用戶均請求自身的對象)

AddTransient 每次請求對象都是不同的(暫未找到合適的應用場景,如有合適的請告知

 

.Net Core自身的IOC容器比較簡單,如果想要更多的功能和擴展,還需要第三方的框架支持。

2、第三方IOC容器

.Net Core 有多種三方容器 如:Autofac、DryIoc、Grace、lightInject等等。評價較好的是Autofac,我們這里也使用Autofac

在 Package Manager Console中輸入如下命令,安裝Autofac包

Install-Package Autofac -Version 6.1.0
Install-Package Autofac.Extensions.DependencyInjection -Version 7.1.0

替換默認的IOC容器,在Program類中的CreateHostBuilder方法中 將默認ServiceProviderFactory指定為AutofacServiceProviderFactory

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

在Startup類中添加如下方法:

public void ConfigureContainer(ContainerBuilder builder)
{
    var basePath = AppContext.BaseDirectory;
    //Service所在程序集
    string servicePath = Path.Combine(basePath, "MServices.dll");
    Assembly serviceDll = Assembly.LoadFrom(servicePath);
    //Repository層所在程序集
    string repositoryPath = Path.Combine(basePath, "MRepository.dll");
    Assembly repositoryDll = Assembly.LoadFrom(repositoryPath);

    builder.RegisterAssemblyTypes(serviceDll)
        .AsImplementedInterfaces()
        .InstancePerDependency();
    builder.RegisterAssemblyTypes(repositoryDll)
        .AsImplementedInterfaces()
        .InstancePerDependency();
}

移除之前ConfigureServices中的注入

services.AddScoped<IUserInfoRepository, UserInfoRepository>();
services.AddScoped<IUserInfoServices, UserInfoServices>();

運行項目,並調用接口,調用正常,說明Autofac配置成功

五、結語

本文以殺手行刺為例簡單說明了依賴注入、控制反轉、IOC容器的概念及其聯系。如有不正之處,請指正,感謝!

代碼地址:https://gitee.com/sirius_machao/mweb-api

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM