Loading

WinUI3 项目使用 .NET Generic Host

NuGet Gallery | Microsoft.Extensions.Hosting 8.0.1

.NET Generic Host - .NET | Microsoft Learn

本文用于记录使用 .NET Generic Host 来管理 WinUI3 项目。

管理 WPF 项目可以参考:

使用 Hosting 构建 WPF 程序 - prism 篇

WinUI3 + .NET Generic Host

1 添加一个文件,如 Program.cs,用于编写自定义的 Main 入口点。

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

namespace GamePad.App;

internal static class Program
{
    static void Main(string[] args)
    {
        // TODO
    }
}

2 配置 csproj, 禁用默认的程序启动入口,配置新的入口。

同时引入 Microsoft.Extensions.Hosting

  <PropertyGroup>
    <!-- 禁用默认入口点生成 -->
    <DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants>
    <StartupObject>GamePad.App.Program</StartupObject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
  </ItemGroup>

3 添加 WinUiHostedService 作为 Host 的一个服务

引用自 c# - Why doesn't the .NET Generic Host stop when used with WinUI3? - Stack Overflow

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;

namespace GamePad.App;

public class WinUiHostedService<TApplication> : IHostedService, IDisposable
    where TApplication : Application, new()
{
    private readonly IHostApplicationLifetime _hostApplicationLifetime;
    private readonly IServiceProvider _serviceProvider;

    public WinUiHostedService(
        IHostApplicationLifetime hostApplicationLifetime,
        IServiceProvider serviceProvider
    )
    {
        _hostApplicationLifetime = hostApplicationLifetime;
        _serviceProvider = serviceProvider;
    }

    public void Dispose() { }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        var thread = new Thread(Main);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    private void Main()
    {
        WinRT.ComWrappersSupport.InitializeComWrappers();
        Application.Start(
            (p) =>
            {
                var context = new DispatcherQueueSynchronizationContext(
                    DispatcherQueue.GetForCurrentThread()
                );
                SynchronizationContext.SetSynchronizationContext(context);
                var application = new TApplication();
            }
        );
        _hostApplicationLifetime.StopApplication();
    }
}

4 完成 Main 方法

internal static class Program
{
    static void Main(string[] args)
    {
        Host.CreateDefaultBuilder()
            .ConfigureServices(services =>
            {
                services.AddHostedService<WinUiHostedService<App>>();
            })
            .Build()
            .Run();
    }
}

prism

prism 目前还没有官方支持 WinUI3

Prism for WinUI 3 · PrismLibrary/Prism · Discussion #2675 · GitHub
GitHub - PrismLibrary/Prism

参考内容

GitHub - abdes/winui-override-main: A WinUI 3 visual studio solution for an application that uses a custom Main entry point instead of the default XAML entry point.

How to create a single-instanced WinUI app with C# - Windows apps | Microsoft Learn

c# - Why doesn't the .NET Generic Host stop when used with WinUI3? - Stack Overflow

posted @ 2025-05-17 22:50  J.晒太阳的猫  阅读(110)  评论(0)    收藏  举报