如何在.NET Standard类库中处理WinForms、Blazor等目标特定方法?
问题解答
1. 是否应该采用依赖注入实现?
完全应该。依赖注入(DI)是处理这类跨框架/平台的抽象依赖的标准方案,它能让你的.NET Standard类库彻底与具体应用的UI实现解耦,只依赖抽象接口,不用关心底层是WinForms的MessageBox还是Blazor的JS弹窗。这样类库的业务逻辑可以保持纯净,同时支持多平台适配,符合开闭原则。
2. 实现大纲(基于DI容器)
步骤1:在.NET Standard 2.0类库中定义抽象接口
首先在共享类库中定义统一的服务抽象,比如处理消息显示的接口:
// 共享类库 / Interfaces/IMessageService.cs public interface IMessageService { // 可根据需求定义同步/异步方法 void ShowMessage(string message); Task ShowMessageAsync(string message); } // 共享类库中的业务逻辑类,依赖抽象接口 public class SharedBusinessLogic { private readonly IMessageService _messageService; // 构造函数注入抽象服务 public SharedBusinessLogic(IMessageService messageService) { _messageService = messageService; } public void DoBusinessOperation() { // 业务逻辑处理... _messageService.ShowMessage("操作完成!"); // 或者异步调用 // await _messageService.ShowMessageAsync("异步操作完成!"); } }
步骤2:在各应用中实现接口
WinForms .NET Framework 4.7.2实现
先安装Microsoft.Extensions.DependencyInjection NuGet包(.NET Framework 4.7.2支持这套DI体系),然后实现接口:
// WinForms项目 / Services/WinFormsMessageService.cs public class WinFormsMessageService : IMessageService { public void ShowMessage(string message) { MessageBox.Show(message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } public Task ShowMessageAsync(string message) { // 同步方法包装成异步 return Task.Run(() => MessageBox.Show(message, "异步提示")); } }
然后在WinForms的启动代码中配置DI容器:
// Program.cs static class Program { public static IServiceProvider ServiceProvider { get; private set; } [STAThread] static void Main() { // 构建DI容器 var services = new ServiceCollection(); services.AddSingleton<IMessageService, WinFormsMessageService>(); services.AddSingleton<SharedBusinessLogic>(); ServiceProvider = services.BuildServiceProvider(); Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // 从容器获取主窗体(如果主窗体依赖服务,可构造函数注入) Application.Run(ServiceProvider.GetRequiredService<MainForm>()); } } // MainForm.cs public partial class MainForm : Form { private readonly SharedBusinessLogic _businessLogic; public MainForm(SharedBusinessLogic businessLogic) { InitializeComponent(); _businessLogic = businessLogic; } private void btnExecute_Click(object sender, EventArgs e) { _businessLogic.DoBusinessOperation(); } }
Blazor .NET 6实现
在Blazor项目中实现接口,依赖IJSRuntime调用JS弹窗:
// Blazor项目 / Services/BlazorMessageService.cs public class BlazorMessageService : IMessageService { private readonly IJSRuntime _jsRuntime; public BlazorMessageService(IJSRuntime jsRuntime) { _jsRuntime = jsRuntime; } public void ShowMessage(string message) { // 同步调用JS方法(Blazor中推荐异步,此处为示例) _jsRuntime.InvokeVoidAsync("alert", message).Wait(); } public async Task ShowMessageAsync(string message) { await _jsRuntime.InvokeVoidAsync("alert", message); } }
然后在Program.cs中注册服务:
// Program.cs var builder = WebApplication.CreateBuilder(args); // 添加Blazor服务 builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); // 注册自定义服务 builder.Services.AddScoped<IMessageService, BlazorMessageService>(); builder.Services.AddScoped<SharedBusinessLogic>(); var app = builder.Build(); // 中间件配置... app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
在Blazor组件中使用:
@page "/" @inject SharedBusinessLogic BusinessLogic <button @onclick="ExecuteOperation">执行操作</button> @code { private void ExecuteOperation() { BusinessLogic.DoBusinessOperation(); } }
3. 可以不使用DI容器实现吗?
当然可以,这种方式常被称为“手动注入”或“简易DI”,不需要依赖任何DI容器,直接在应用层手动创建具体实现的实例,传递给共享类库的业务逻辑类。
实现示例:
WinForms中手动注入
// MainForm.cs private void btnExecute_Click(object sender, EventArgs e) { // 手动创建具体实现实例 var messageService = new WinFormsMessageService(); // 传递给业务逻辑类 var businessLogic = new SharedBusinessLogic(messageService); businessLogic.DoBusinessOperation(); }
Blazor中手动注入
@page "/" @inject IJSRuntime JsRuntime <button @onclick="ExecuteOperation">执行操作</button> @code { private void ExecuteOperation() { var messageService = new BlazorMessageService(JsRuntime); var businessLogic = new SharedBusinessLogic(messageService); businessLogic.DoBusinessOperation(); } }
这种方式的好处是轻量,不需要引入DI容器包;缺点是当依赖关系复杂时,手动创建和传递实例会变得繁琐,不利于维护。适合简单场景,复杂场景还是推荐用DI容器。
内容的提问来源于stack exchange,提问作者Thomas853
相关产品推荐
相关产品推荐

