You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:07:57