You need to enable JavaScript to run this app. WPF中借助Microsoft.Extensions.Hosting实现ASP.NET Core依赖注入
优惠活动
大模型
产品
解决方案
定价
更多

WPF中借助Microsoft.Extensions.Hosting实现ASP.NET Core依赖注入

你现在的代码跑不起来,根本原因是 IHost.Run() 执行的是通用主机的后台服务循环,它不会触发WPF要求的UI线程消息循环初始化流程,自然没法正常拉起应用。
你之前见过的那段优雅实现,本质就是把WPF的启动逻辑封装成通用主机的托管服务,全程从DI容器取实例,既保留了通用主机和ASP.NET Core一致的配置、日志、DI体验,又完全兼容WPF的运行规则,刚好就是你要的效果。

前置配置检查(漏了这些代码写对也会编译冲突)

  • 确认csproj里已经加了 <EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>,拦住系统自动生成的Main入口
  • 找到App.xaml,把它的生成操作从默认的ApplicationDefinition改成Page,不然编译时还是会自动塞启动代码,和你自己写的Main逻辑冲突
  • 把App.xaml上硬写的StartupUri删掉,所有窗口都从DI容器获取,不然硬编码的窗口会绕过注入逻辑,拿不到构造函数里的服务

核心实现代码

1. 修正后的Program入口

和你现有代码结构基本一致,仅补充托管服务的注册:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                // 照常注册WPF组件和业务服务
                services.AddSingleton<App>();
                services.AddSingleton<MainWindow>();
                // 注册负责衔接WPF和主机生命周期的托管服务
                services.AddHostedService<WpfHostService>();
            })
            .Build()
            .Run();
    }
}

2. 生命周期衔接核心逻辑

这就是你记忆里「从IServiceProvider获取App实例再调用Application.Run」的核心部分:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;
using System.Threading.Tasks;

public class WpfHostService : IHostedService
{
    private readonly IServiceProvider _serviceProvider;
    private App _wpfApp;

    public WpfHostService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // 从DI容器拿到注册好的App单例
        _wpfApp = _serviceProvider.GetRequiredService<App>();
        
        // 异步运行WPF的消息循环,避免阻塞主机启动流程
        return Task.Run(() =>
        {
            // 主窗口也从DI容器获取,保证注入链路完整生效
            var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
            _wpfApp.Run(mainWindow);
        }, cancellationToken);
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // 主机停止时主动关闭WPF消息循环,避免进程残留
        _wpfApp?.Shutdown();
        return Task.CompletedTask;
    }
}

常见踩坑提示

  • 别在App的构造函数里直接操作UI组件,所有UI交互必须等App.Run启动消息循环之后再执行
  • 需要处理全局异常、应用退出逻辑时,直接在WpfHostService里通过拿到的App实例订阅事件即可,不需要依赖App.xaml的自动事件挂载
  • 这种写法下,你可以像开发ASP.NET Core项目一样在ConfigureServices里注册数据库、配置、业务服务,窗口构造函数里直接注入,体验完全一致

内容的提问来源于stack exchange,提问作者Summpot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 15:54:01