站長:Winform 的分享文章不多,這個技術相對來說已經十分穩定了,該有的都有了,今天分享其他號寫的 Winform 依賴注入一文,希望做相關開發的朋友能有新的體會。
1. 介紹
關於依賴注入是什麼?依賴注入是一種具體的編碼技巧,對我來說最明顯的就是解決程式碼的耦合性。
2. 目的
ASP.NET Core 中本身容器已經建立好了,只需要往容器加入服務即可,但是在 Winform 中預設還是透過 new 的方式來進行操作的(雖然我已經升級成了 .Net6),最近在把一個開源專案進行增加自用的功能,然後我順便將原來的 .NET Framework 升級為 .NET Core,然後就想用依賴注入方式去試試了。
C/S 程式碼寫得少,如有不對,麻煩指正。
3. 操作
本文範例環境:VS2022、.Net6、Windows 表單應用程式
4. 準備
範例包含以下程式碼
表單:Form1、Form2
Service:IUserservice、Userservice、IOrderService、OrderService
public interface IUserservice
{
string GetName();
}
public class UserService : IUserservice
{
public string GetName()
{
return "IUserservice";
}
}
public interface IOrderService
{
string GetName();
}
public class OrderService : IOrderService
{
public string GetName()
{
return "IOrderService";
}
}
5. 場景
在 Form1 透過建構函式注入 IUserservice,並且在 Load 事件裡面呼叫 IUserservice 的取得名稱方法,點擊頁面按鈕後讓 Form2 顯示,Form2 中透過依賴注入 IOrderService 在 Load 事件裡面呼叫 IOrderService 的取得名稱方法。如果可以多次操作不報錯就是成功。
6. 開始
引用元件
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
增加了一個 ServiceProviderHelper 的操作類別
public static class ServiceProviderHelper
{
/// <summary>
/// 全域服務提供者
/// </summary>
public static IServiceProvider ServiceProvider { get; private set; } = null!;
/// <summary>
/// 初始化建構 ServiceProvider 物件
/// </summary>
/// <param name="serviceProvider"></param>
/// <exception cref="ArgumentNullException"></exception>
public static void InitServiceProvider(ServiceProvider serviceProvider)
{
ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider));
ServiceProvider = serviceProvider;
}
/// <summary>
/// 取得 Form 服務
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static Form GetFormService(Type type)
{
var service = ServiceProvider.GetRequiredService(type);
if (service is Form fService)
{
return fService;
}
else
{
throw new ArgumentException($"{type.FullName} is not a Form");
}
}
/// <summary>
/// 取得服務
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static T GetService<T>() where T : class
{
return ServiceProvider.GetRequiredService<T>();
}
}
修改 Program 方法
internal static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
private static void Main()
{
// .NET 6 寫法(之前是三行合一行)
ApplicationConfiguration.Initialize();
// 建立服務容器
var services = new ServiceCollection();
// 加入服務註冊
ConfigureServices(services);
// 建構 ServiceProvider 物件
ServiceProviderHelper.InitServiceProvider(services.BuildServiceProvider());
// 取得指定服務
var main = ServiceProviderHelper.ServiceProvider.GetRequiredService<Form1>();
Application.Run(main);
}
/// <summary>
/// 注入服務
/// </summary>
/// <param name="services"></param>
public static void ConfigureServices(IServiceCollection services)
{
// 批次注入可以使用 Scrutor 或者自己封裝
services.AddScoped<IUserservice, UserService>();
services.AddScoped<IOrderService, OrderService>();
// 其他的表單也可以注入在此處
services.AddSingleton(typeof(Form1));
services.AddTransient(typeof(Form2));
}
}
分別在 Form1 和 Form2 進行注入
private readonly IUserservice _userservice;
public Form1(IUserservice userservice)
{
InitializeComponent();
_userservice = userservice;
}
private readonly IOrderService _orderService;
public Form2(IOrderService orderService) : this()
{
_orderService = orderService;
}
點擊 Form1 表單按鈕讓 Form2 表單顯示
private void button1_Click(object sender, EventArgs e)
{
var form2 = ServiceProviderHelper.GetFormService(typeof(Form2));
form2.Show();
}
正常操作幾次並沒有發現異常。
7. 資料
在 .NET Core 3.1 上基於 Winform 實現依賴注入實例:http://www.ty2y.com/study/znetcore3.1sjywinformsxylzrsl.html