大家好,我是張飛洪,感謝您的閱讀,我會不定期和你分享學習心得,希望我的文章能成為你成長路上的墊腳石,讓我們一起精進。
本章是《定製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
,感謝您的閱讀。