站長:winform 的分享文章不多,這個技術相對來說已經十分穩定了,該有的都有了,今天分享其他號寫的 winform 依賴注入一文,希望做相關開發的朋友能有新的體會。
1. 居間
關於依賴注入是什麼?依賴注入是一種具體的編碼技巧,對我來說最明顯的就是解決代碼的耦合性。
2. 目的
asp.net core 中本身容器容器已經創建好了,只需要往容器添加服務即可,但是在 winform 中默認還是通過 new 的方式來進行操作的(雖然我已經升級成了.net6),最近在把一個開源項目進行增加自用的功能,然後我順帶將原來的 netf 升級為 netcore,然後就想用依賴注入方式去試試了。
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>
/// 获取Form服务
/// </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>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
//.net6写法 之前是三行合一行
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 core3.1 上基於 winform 實現依賴注入實例:http://www.ty2y.com/study/znetcore3.1sjywinformsxylzrsl.html