一、前言
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