Program.cs
using Microsoft.Extensions.DependencyInjection;
using WinFormsApp1.Helper;
namespace WinFormsApp1;
internal static class Program
{
// 服務容器,用於儲存和提供已註冊的服務
public static IServiceProvider ServiceProvider { get; set; }
[STAThread]
static void Main()
{
// 初始化應用程式配置
ApplicationConfiguration.Initialize();
// 配置服務容器
var serviceCollection = new ServiceCollection().InJection();
// 構建服務提供者
ServiceProvider = serviceCollection.BuildServiceProvider();
// 從服務提供者中獲取指定鍵對應的Form型別服務
var form = ServiceProvider.GetKeyedService<Form>(nameof(PictureBoxTest));
// 啟動應用程式並傳入獲取到的Form例項,使應用程式開始執行並展示相應介面
Application.Run(form);
}
}
DIHelper.cs
using Microsoft.Extensions.DependencyInjection;
namespace WinFormsApp1.Helper;
public static class DIHelper
{
// 擴充套件方法,用於向IServiceCollection中註冊特定的Form服務
public static IServiceCollection InJection(this IServiceCollection service)
{
// 以nameof(BaseControlTest)為鍵,註冊BaseControlTest型別的Form為單例服務
service.AddKeyedSingleton<Form, BaseControlTest>(nameof(BaseControlTest));
// 以nameof(PictureBoxTest)為鍵,註冊PictureBoxTest型別的Form為單例服務
service.AddKeyedSingleton<Form, PictureBoxTest>(nameof(PictureBoxTest));
return service;
}
}
以下是關於本程式碼中所運用的依賴注入方法的詳細闡述:
一、整體流程概述
在Program.cs
檔案的Main
方法中,整個依賴注入及應用程式啟動的流程如下:
首先,執行ApplicationConfiguration.Initialize();
語句,以此完成應用程式配置的初始化操作,這一步驟為後續的程式執行奠定了基礎配置環境。
隨後,建立一個ServiceCollection
的例項,並呼叫自定義的擴充套件方法InJection
對其進行服務容器的配置操作。透過該擴充套件方法,能夠向服務容器中註冊所需的各類服務。
在完成服務容器的配置後,利用已配置好的ServiceCollection
例項構建出IServiceProvider
,此即為服務提供者。它扮演著在應用程式執行過程中提供已註冊服務的關鍵角色。
最後,透過ServiceProvider.GetKeyedService<Form>(nameof(PictureBoxTest));
語句,依據特定的鍵(在此為nameof(PictureBoxTest)
)從服務提供者中獲取對應的Form
型別服務例項。接著,將獲取到的該Form
例項傳遞給Application.Run
方法,從而啟動應用程式的訊息迴圈,使應用程式得以正常執行並展示出相應的介面。
二、服務序號產生器制
在DIHelper.cs
檔案中,定義了DIHelper
靜態類,其中包含了用於服務註冊的擴充套件方法InJection
。
該擴充套件方法主要針對IServiceCollection
型別進行擴充套件,其接收一個IServiceCollection
例項作為引數(此引數在Program.cs
的Main
方法中進行建立並傳入)。
在InJection
擴充套件方法內部,藉助AddKeyedSingleton
方法實現了兩種不同型別的Form
服務註冊操作:
其一,以nameof(BaseControlTest)
作為鍵,將BaseControlTest
型別的Form
註冊為單例服務。這意味著在整個應用程式的生命週期內,只會存在一個該型別的Form
例項,並且該例項將在需要時由服務提供者統一提供。
其二,以nameof(PictureBoxTest)
為鍵,把PictureBoxTest
型別的Form
同樣註冊為單例服務。其原理與上述類似,確保在應用程式執行過程中,對於該型別Form
服務的獲取始終指向同一個例項。
三、服務獲取與應用
回到Program.cs
的Main
方法中,當成功構建服務提供者ServiceProvider
之後:
透過ServiceProvider.GetKeyedService<Form>(nameof(PictureBoxTest));
這一語句,依據nameof(PictureBoxTest)
這個特定的鍵,從服務提供者中準確獲取到對應的Form
型別服務例項。此處所獲取到的例項,實際上就是之前在服務註冊階段以nameof(PictureBoxTest)
為鍵所註冊的PictureBoxTest
型別的Form
服務例項(前提是假設PictureBoxTest
是一個繼承自Form
的具體型別)。
最終,將獲取到的Form
例項傳遞給Application.Run
方法,以此啟動應用程式並使其能夠利用所注入的服務來完成相關的功能。具體的功能實現則取決於PictureBoxTest
等各類表單類內部的具體邏輯設計。
值得一提的是,在程式碼中可能存在一處細微的瑕疵,即InJection
方法名或許應當為Injection
,在後續的程式碼最佳化過程中可對此予以關注並修正。