在 .NET 开发中,依赖注入(DI)是一种常用的设计模式,它有助于减少代码之间的耦合,使得代码更加模块化和易于测试。虽然在 ASP.NET Core 中内置了强大的依赖注入支持,但在 Windows Forms(WinForms)应用程序中实现 DI 可能会比较复杂。本文将介绍如何在 WinForms 应用中使用 Scrutor 来简化服务注册过程,并提供一些实用的示例。
Scrutor 是一个扩展库,它扩展了 .NET Core 的 IServiceCollection,提供了更多灵活的方式来注册服务,尤其是通过扫描程序集来自动注册服务非常实用。这在大型项目中尤其有用,可以避免手动注册每个服务。
首先,确保你有一个 WinForms 项目。在 Visual Studio 中创建一个新的 WinForms .NET Core 项目。
在项目中,我们需要添加以下 NuGet 包:
你可以通过 NuGet 包管理器或使用包管理控制台来安装这些包:
BashInstall-Package Microsoft.Extensions.DependencyInjection Install-Package Microsoft.Extensions.Hosting Install-Package Scrutor
首先,我们需要定义一些服务和接口。例如,我们创建一个 IMessageService
接口和一个实现该接口的 MessageService
类:
C#public interface IMessageService
{
void SendMessage(string message);
}
public class MessageService : IMessageService
{
public void SendMessage(string message)
{
MessageBox.Show(message, "Message");
}
}
在 WinForms 应用中配置 DI 容器和 Host。我们可以在 Program.cs
中设置:
C#internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
var host = CreateHostBuilder().Build();
using (var serviceScope = host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var mainForm = services.GetRequiredService<Form1>();
Application.Run(mainForm);
}
}
static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureServices((hostContext, services) =>
{
services.Scan(scan => scan
.FromAssemblyOf<Form1>() // 从 Form1 所在的程序集开始扫描
.AddClasses(classes => classes.AssignableTo<IMessageService>()) // 添加所有实现 IMessageService 接口的类
.AsImplementedInterfaces() // 将它们注册为实现的接口
.WithScopedLifetime()); // 使用作用域生命周期
services.AddScoped<Form1>(); // 将 Form1 注册为作用域服务
});
}
在 MainForm.cs
,我们可以通过构造函数注入使用 IMessageService
:
C#public partial class MainForm : Form
{
private readonly IMessageService _messageService;
public MainForm(IMessageService messageService)
{
InitializeComponent();
_messageService = messageService;
}
private void btnShowMessage_Click(object sender, EventArgs e)
{
_messageService.SendMessage("hello world!");
}
}
C#public interface ILoggingService
{
void Log(string message);
}
LoggingService服务
C#public class LoggingService : ILoggingService
{
public void Log(string message)
{
// 实现日志记录逻辑,例如输出到控制台
File.AppendAllText("app.log", message);
}
}
C#public partial class FrmEdit : Form
{
private readonly ILoggingService _loggingService;
public FrmEdit(ILoggingService loggingService)
{
InitializeComponent();
_loggingService = loggingService;
}
private void btnWriteLog_Click(object sender, EventArgs e)
{
_loggingService.Log("FrmEdit...");
}
}
C#private readonly IMessageService _messageService;
private readonly ILoggingService _loggingService;
private readonly IServiceProvider _serviceProvider;
public Form1(IMessageService messageService, ILoggingService loggingService, IServiceProvider serviceProvider)
{
InitializeComponent();
this._messageService = messageService;
_loggingService = loggingService;
_serviceProvider = serviceProvider;
}
private void btnShowEdit_Click(object sender, EventArgs e)
{
using (var scope = _serviceProvider.CreateScope())
{
var frmEdit = scope.ServiceProvider.GetRequiredService<FrmEdit>();
frmEdit.ShowDialog();
}
}
C#static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureServices((hostContext, services) =>
{
services.Scan(scan => scan
.FromAssemblyOf<Form1>() // 从 Form1 所在的程序集开始扫描
.AddClasses(classes => classes.AssignableTo<IMessageService>()) // 添加所有实现 IMessageService 接口的类
.AddClasses(classes => classes.AssignableTo<ILoggingService>()) // 添加所有实现 ILoggingService 接口的类
.AsImplementedInterfaces() // 将它们注册为实现的接口
.WithScopedLifetime()); // 使用作用域生命周期
services.AddScoped<Form1>(); // 将 Form1 注册为作用域服务
services.AddScoped<FrmEdit>(); // 将 Form2 注册为作用域服务
services.AddScoped<IMessageService, MessageService>();
services.AddScoped<ILoggingService, LoggingService>();
});
通过使用 Scrutor 和 Microsoft.Extensions.DependencyInjection,我们可以在 WinForms 应用中轻松实现依赖注入,这为我们提供了更高的灵活性和可测试性。上述示例展示了如何自动扫描和注册服务,以及如何在应用程序中使用它们。这种方法可以帮助我们构建更加解耦和维护更加简单的 WinForms 应用。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!