在ASP.NET Core中,依賴注入(DI)是非常重要的特性。本文將深入探討ASP.NET Core源碼中的容器IOC和依賴注入的實現原理。
什么是IoC
Inversion of Control(IoC)是指將控制權反轉過來,即由系統來控制程序的執行流程。傳統的程序都是由開發人員自己編寫代碼來控制程序的執行流程,而IoC則是將這種“主動權”交給了系統。
在IoC中,對象的創建和管理由框架或容器來完成,這些對象也被稱為服務。應用程序通過請求獲取服務,而不是直接創建服務對象。
什么是DI
Dependency Injection(DI)是IoC的一種具體實現方式。在DI中,服務提供方和服務使用方之間的耦合關系由第三方組件(DI容器)來處理。容器負責實例化服務,并將其注入到需要該服務的類中。
ASP.NET Core中的DI容器可以幫助我們解決應用程序中的對象管理問題,例如創建對象、管理對象的生命周期等。
ASP.NETCore DI容器的注冊
在ASP.NET Core中,我們可以使用以下方法將服務注冊到DI容器:
services.AddScoped<IMyService, MyService>();
其中,AddScoped方法將服務注冊為Scoped生命周期,IMyService是服務接口,MyService是服務的實現。
ASP.NETCore DI容器的解析
在ASP.NET Core中,我們可以使用以下代碼從DI容器中解析服務:
var service = serviceProvider.GetService<IMyService>();
其中,GetService方法從容器中解析出指定類型的服務對象,返回一個IServiceProvider類型的實例。
ASP.NETCore DI容器的生命周期
ASP.NET Core中DI容器的生命周期如下:
- Transient:每次請求都創建一個新的服務實例。
- Scoped:在同一作用域(例如同一HTTP請求)中,每次請求只創建一個服務實例。
- Singleton:整個應用程序中只創建一個服務實例。
實現原理
ASP.NET Core中的DI容器基于
Microsoft.Extensions.DependencyInjection庫實現。該庫主要包含以下三個核心類:
- ServiceCollection:服務集合,用于注冊服務。
- ServiceProvider:服務提供者,用于解析服務。
- ServiceDescriptor:服務描述符,用于描述服務的類型、實現和生命周期。
在ASP.NET Core中,服務提供者(ServiceProvider)采用了服務提供者模式。服務提供者模式是指,在軟件系統中,提供一種機制,能夠讓開發人員更加方便地獲取系統所提供的各種服務。服務提供者模式的核心思想就是將服務的創建和使用分離開來,即服務的創建交給容器去處理,而服務的使用則由開發人員自行控制。
為了實現服務提供者模式,我們需要一個容器來管理服務。在ASP.NET Core中,容器主要用于注冊服務、解析服務、生命周期管理等。
容器一般包含兩個主要角色:服務描述符(ServiceDescriptor)和服務提供者(ServiceProvider)。服務描述符用于描述服務,例如服務接口類型、服務實現類型、生命周期等;而服務提供者則用于創建和管理服務實例。
ServiceCollection容器
在ASP.NET Core中,我們使用ServiceCollection容器來注冊服務。ServiceCollection類繼承于IServiceCollection接口,用于注冊服務描述符并最終構建出ServiceProvider容器。ServiceCollection提供了一系列方便的方法來簡化服務注冊的過程。例如,通過調用AddTransient、AddScoped、AddSingleton等方法,我們可以輕松地注冊服務。
ServiceCollection會在構建出ServiceProvider容器之前驗證注冊的服務描述符,以確保其合法性。例如,當注冊多個同一服務類型的描述符時,ServiceCollection會拋出異常。另外,在
ServiceCollection.BuildServiceProvider() 方法中,容器將遞歸檢查和解析所有服務描述符,構造出DI框架的核心實例(ServiceProvider)。
ServiceProvider容器
ServiceProvider是一個抽象類,表示服務提供者。在ASP.NET Core中,我們常用的是ServiceProvider的派生類:ServiceProviderEngine。ServiceProviderEngine是IServiceProvider接口的一個實現,它封裝了所有服務實例的創建和管理過程,可以通過ServiceProviderFactory 派生類中的CreateServiceProvider來創建或指定它。
在ServiceProviderEngine中,每個服務都有一個對應的ServiceCallSite(調用站點),用于記錄服務的描述信息。ServiceCallSite主要由以下三個部分組成:
- CallType,表示服務的運行時類型。
- ImplementationType,表示服務的實現類型。
- Cache,表示服務實例的緩存。
在獲取服務實例時,ServiceProviderEngine先從緩存中查找服務實例,如果沒有找到則根據 CallType 和 ImplementationType 創建新的服務實例。同時,也會處理服務的生命周期,根據服務描述符中的Lifetime設置,選擇相應的范圍進行限制。
集成Autofac等IOC框架
ASP.NET Core自帶的依賴注入容器已經能夠滿足大多數場景需求,但是有時候需要在項目中使用其他的IOC框架,比如Autofac。下面將介紹如何在ASP.NET Core中集成Autofac,以實現更加便捷的依賴注入。
Autofac是一個用于依賴注入(Dependency Injection)的開源.NET容器。它提供了一種簡單而靈活的方式來管理對象的創建和生命周期,使得應用程序的組件可以松耦合、可測試和可擴展。
以下是一些關于Autofac的鏈接:
- Autofac官方網站:https://autofac.org/
- Autofac在Github上的倉庫:https://github.com/autofac/Autofac
- Autofac的文檔:https://autofac.readthedocs.io/
- Autofac的NuGet包:https://www.nuget.org/packages/Autofac/
以下是一些使用Autofac的示例代碼:
- 注冊和解析一個簡單的依賴關系:
// 創建容器構建器
var builder = new ContAInerBuilder();
// 注冊依賴關系
builder.RegisterType<MyDependency>().As<IMyDependency>();
// 構建容器
var container = builder.Build();
// 解析依賴關系
var myDependency = container.Resolve<IMyDependency>();
- 使用構造函數注入:
public class MyClass
{
private readonly IMyDependency _myDependency;
public MyClass(IMyDependency myDependency)
{
_myDependency = myDependency;
}
// ...
}
// 注冊依賴關系
builder.RegisterType<MyClass>();
// 解析依賴關系
var myClass = container.Resolve<MyClass>();
- 使用屬性注入:
public class MyClass
{
[Autowired]
public IMyDependency MyDependency { get; set; }
// ...
}
// 注冊依賴關系
builder.RegisterType<MyClass>();
// 解析依賴關系
var myClass = container.Resolve<MyClass>();
這些示例只是Autofac的一小部分功能,更多詳細的使用方法和示例可以在官方文檔中找到。
安裝Autofac
首先,在ASP.NET Core項目中安裝Autofac和
Autofac.Extensions.DependencyInjection NuGet包。
可以通過NuGet包管理器或者通過命令行來安裝:
- NuGet包管理器:在Visual Studio中打開NuGet包管理器,搜索并安裝Autofac和Autofac.Extensions.DependencyInjection包。
- 命令行:在項目根目錄下打開命令行工具,并執行以下兩個命令:
dotnet add package Autofac
dotnet add package Autofac.Extensions.DependencyInjection
配置Autofac
在ASP.NET Core中,可以通過IServiceCollection接口來注冊服務描述符,并最終構建出ServiceProvider容器。而Autofac也提供了相應的配置類來實現服務的注冊和解析。
下面是一個簡單的Autofac配置示例:
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// 注冊服務
builder.RegisterType<MyService>().As<IMyService>();
// 將Autofac容器作為ServiceProvider容器
builder.Populate(services);
}
}
在上述代碼中,我們創建了一個Autofac的Module類,并在其Load方法中進行服務注冊。這里我們將MyService類注冊為IMyService的實現類型,并將Autofac容器作為ServiceProvider容器。
注冊Autofac容器
最后,我們需要在ASP.NET Core的ConfigureServices方法中注冊Autofac容器:
public void ConfigureServices(IServiceCollection services)
{
// 配置Autofac
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacModule());
// 將Autofac容器設置為默認的依賴注入容器
var container = builder.Build();
return new AutofacServiceProvider(container);
// 注冊其他服務
services.AddMvc();
}
在上述代碼中,我們通過AutofacModule來配置Autofac,并創建了Autofac容器。最后,我們將Autofac容器設置為默認的依賴注入容器,即返回AutofacServiceProvider對象。這樣就完成了Autofac與ASP.NET Core的集成。
總結
通過對ASP.NET Core DI容器的注冊、解析和生命周期等方面進行深入探討,我們能夠更好地理解容器IOC和依賴注入的實現原理。同時,我們也能更好地使用ASP.NET Core的DI容器來進行應用程序開發,從而提高應用程序的性能和可維護性。
參考資料:
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-7.0