本章是《定制ASP NET 6.0框架系列文章》的第三篇。在本章,我們將學習ASP.NET Core
的依賴項注入(DI)以及如何自定義它。
我們將討論以下主題:
使用不同的DI容器
探索ConfigureServices方法
使用其他的ServiceProvider
Scrutor簡介
技術準備
我們使用以下命令(你可以在console, shell,
或Bash
終端),創建一個MVC
應用:
dotnet new mvc -n DiSample -o DiSample
在Visual Studio中打開項目,或在控制臺中鍵入以下命令,在Visual Studio Code
中打開項目:
cd DiSample
code .
使用不同的DI容器
在大多數項目中,我們其實不需要使用不同的DI容器。ASP.NET Core
中的現有DI基本上滿足我們的需要。但是,你可能喜歡其他DI容器的其他功能:
使用
Ninject
創建一個支持模塊作為輕量級依賴項的應用程序。比如,您可能希望將模塊放入特定目錄中,并在應用程序中自動注冊這些模塊。在應用程序外部的配置文件中,比如,在XML或JSON文件中,而不是僅在C#中配置服務。這是各種DI容器中的常見功能,但
ASP.NET Core
中尚不支持。在運行時添加服務,獲取動態的DI容器,這也是一些DI容器中的常見特性。
現在,讓我們看看ConfigureServices
方法是如何操作的。
探索ConfigureServices
方法
我們將當前的ConfigureServices
方法與以前的長期支持版本(TLS)進行比較,看看有什么變化。如果您使用版本3.1創建的ASP.NET Core
項目,并打開Startup.cs
文件,配置服務的方法如下所示:
public void ConfigureServices(IServiceCollection services)
{services.Configure<CookiePolicyOptions>(options =>{options.CheckConsentNeeded = context => true;});services.AddControllersWithViews();services.AddRazorPages();
}
相反,在?ASP.NET Core 6.0
,沒有啟動Startup.cs
,服務的配置在Startup.cs
中進行,如下所示:
var?builder?=?WebApplication.CreateBuilder(args);
//?Add?services?to?the?container. builder.Services.AddControllersWithViews();
var?app?=?builder.Build();
// The rest of the file isn't relevant for this chapter
這兩種情況都可以獲得IServiceCollection
,其中默認已經填充了ASP.NET Core
所需的一組服務,比如宿主服務、ConfigureServices
方法之前執行的相關服務。
以上方法中,添加了更多的服務。
首先,將包含
cookie
策略選項的配置類添加到ServiceCollection
。AddMvc()
方法添加MVC框架所需的服務。
到目前為止,我們有大約140個服務注冊到IServiceCollection
。
但是,服務集合不是實際的DI容器,真實的DI容器被包裝在所謂的服務提供者中(ServiceProvider
)。
那么應該如何獲取DI容器呢?
IServiceCollection
有了一個擴展方法,它用于從服務集合中創建IServiceProvider
,代碼如下:
IServiceProvider provider = services.BuildServiceProvider()
ServiceProvider
包含不可變容器,即在運行時無法更改。在ConfigureServices
方法執行后,會在后臺創建IServiceProvider
。
接下來,我們再看下如何在DI定制過程中,替代IServiceProvider
。
使用其他IServiceProvider
如果其他容器已經支持ASP.NET Core
,則更改為其他或自定義DI容器將變得非常容易。通常,第三方DI容器會使用IServiceCollection
做為自己的容器,它通過循環集合將已注冊的服務移動到另一個容器。
我們用第三方容器Autofac
舉個例子。在命令行中鍵入以下命令,加載NuGet
包:
dotnet add package Autofac.Extensions.DependencyInjection
要注冊自定義IoC
容器,通常需要注冊不同的IServiceProviderFactory
,IServiceProviderFactory
將創建一個ServiceProvider
實例。如果第三方容器支持ASP.NET Core
,則必須提供一個該工廠類。如果你要使用Autofac
,則需要使用AutofacServiceProviderFactory
。
我們在Program.cs
中給IHostBuilder
編寫一個擴展方法,內部注冊一個AutofacServiceProviderFactory
:
using Autofac;
using Autofac.Extensions.DependencyInjection;
namespace DiSample; public static class IHostBuilderExtension { ???? public static IHostBuilder?UseAutofacServiceProviderFactory(this IHostBuilder hostbuilder) { ????????hostbuilder.UseServiceProviderFactory (new AutofacServiceProviderFactory()); ???????? return hostbuilder; ????}
}
注意,不要忘記將引入名稱空間:Autofac
和Autofac.Extensions.DependencyInjection
。
要使用此擴展方法,可以在Program.cs
中使用AutofacServiceProvider
:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseAutofacServiceProviderFactory();
// Add services to the container. builder.Services.AddControllersWithViews();
以上通過擴展方法將AutofacServiceProviderFactory
添加到IHostBuilder
中,并啟用Autofac
IoC容器。后續會轉而使用Autofac
向IServiceCollection
添加服務。
再強調一下,除非必要。通常,我們不一定要替換現有的.NET Core
DI容器。
Scrutor簡介
在本章的開頭,我提到了服務的自動注冊,這里可以通過其他DI容器完成。這里介紹一個名為Scrutor
的不錯的NuGet包來實現。Scrutor
通過向.NET Core
?DI容器向IServiceCollection
添加一個擴展方法,用以自動注冊服務。
擴展閱讀
這里介紹一篇關于Scrutor
的非常詳細的博客文章,建議您繼續閱讀這篇文章以了解更多信息。
回顧
通過以上演示,我們將能夠使用任何.NET標準兼容的DI容器替換現有容器。如果您選擇的容器不包括ServiceProvider
,請自己實現一個IServiceProvider
接口,并在其中使用DI容器。如果您選擇的容器沒有提供填充服務的方法,請自行創建自己的方法。循環已注冊的服務并將其添加到另一個容器中。
最后一步聽起來很簡單,實現起來比較費勁,因為需要將所有的IServiceCollection
注冊轉換為其他容器的注冊,它的復雜性取決于其他DI容器的實現細節。
任何時候,我們都可以選擇使用任何與.NET標準兼容的DI容器,替換ASP.NET Core
中的許多默認實現。
在下一章我們將探討如何以不同的方式配置HTTPS
,感謝您的閱讀。