首页 > 编程语言 >使用 Hosting 构建 WPF 程序

使用 Hosting 构建 WPF 程序

时间:2024-11-11 20:43:41浏览次数:5  
标签:AddSingleton void Hosting override protected 构建 services WPF App

.NET Generic Host 是一个通用的应该程序构建方式,不只是适用于 asp.net core,可以用在任何 .NET 项目中。

具体支持的 .NET 框架可以看这里 NuGet Gallery | Microsoft.Extensions.Hosting 8.0.1

.NET Generic Host - .NET | Microsoft Learn

本文用于记录使用 .NET Generic Host 来管理 WPF(使用 Stylet)项目所需的修改,逐步更新,仅供参考。

模板代码:JasonGrass/WpfAppTemplate1: WPF + Stylet + Hosting

1 添加引用

// csproj
  <ItemGroup>
    <PackageReference Include="Stylet" Version="1.3.7" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0-rc.2.24473.5" />
  </ItemGroup>

2 修改 App.xaml

因为要手动使用 Main 函数,不使用默认的 App 的加载,需要将 App.xaml 从 ApplicationDefinition 修改成 Page。

// csproj
  <ItemGroup>
    <ApplicationDefinition Remove="App.xaml" />
    <Page Include="App.xaml" />
  </ItemGroup>

删除 App.xaml 中的 StartUrl,修改成 Stylet 的 ApplicationLoader

// App.xaml
<Application
    x:Class="WpfAppTemplate1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfAppTemplate1"
    xmlns:s="https://github.com/canton7/Stylet">
    <Application.Resources>
        <s:ApplicationLoader>
            <s:ApplicationLoader.Bootstrapper>
                <local:Bootstrapper />
            </s:ApplicationLoader.Bootstrapper>
        </s:ApplicationLoader>
    </Application.Resources>
</Application>

3 App.xaml.cs

添加 Main 函数,创建 IHostBuilder 并运行,然后运行 App.

在 CreateHostBuilder 中,可以扩展所需的 hosting 相关的服务,如配置,日志等。

public partial class App : Application
{
    private static IServiceProvider? _serviceProvider;

    public static IServiceProvider ServiceProvider
    {
        get => _serviceProvider!;
        private set => _serviceProvider = value;
    }

    [STAThread]
    static void Main(string[] args)
    {
        using IHost host = CreateHostBuilder(args).Build();
        ServiceProvider = host.Services;
        host.StartAsync();

        var app = new App();
        app.InitializeComponent();
        app.Run();
    }

    public static T? GetService<T>()
        where T : class
    {
        return ServiceProvider.GetService<T>();
    }

    private static IHostBuilder CreateHostBuilder(string[] args)
    {
        var builder = Host.CreateDefaultBuilder(args)
            .ConfigureServices(serviceCollection =>
            {
                serviceCollection.AddSingleton(_ => Current.Dispatcher);
            });

        return builder;
    }
}

4 Stylet Bootstrapper

因为不在使用 Stylet 自带的 IOC 容器,而使用微软的,需要手动添加一个 MicrosoftDependencyInjectionBootstrapper

这里的代码,可以直接从官方给的模板中复制过来.

public class MicrosoftDependencyInjectionBootstrapper<TRootViewModel> : BootstrapperBase
    where TRootViewModel : class
{
    private ServiceProvider? _serviceProvider;
    private TRootViewModel? _rootViewModel;

    protected virtual TRootViewModel RootViewModel =>
        this._rootViewModel ??= (TRootViewModel)this.GetInstance(typeof(TRootViewModel));

    public IServiceProvider ServiceProvider => this._serviceProvider!;

    protected override void ConfigureBootstrapper()
    {
        var services = new ServiceCollection();
        this.DefaultConfigureIoC(services);
        this.ConfigureIoC(services);
        this._serviceProvider = services.BuildServiceProvider();
    }

    /// <summary>
    /// Carries out default configuration of the IoC container. Override if you don't want to do this
    /// </summary>
    protected virtual void DefaultConfigureIoC(IServiceCollection services)
    {
        var viewManagerConfig = new ViewManagerConfig()
        {
            ViewFactory = this.GetInstance,
            ViewAssemblies = new List<Assembly>() { this.GetType().Assembly },
        };

        services.AddSingleton<IViewManager>(new ViewManager(viewManagerConfig));
        services.AddTransient<MessageBoxView>();

        services.AddSingleton<IWindowManagerConfig>(this);
        services.AddSingleton<IWindowManager, WindowManager>();
        services.AddSingleton<IEventAggregator, EventAggregator>();

        services.AddTransient<IMessageBoxViewModel, MessageBoxViewModel>(); // Not singleton!
        // Also need a factory
        services.AddSingleton<Func<IMessageBoxViewModel>>(() => new MessageBoxViewModel());
    }

    /// <summary>
    /// Override to add your own types to the IoC container.
    /// </summary>
    protected virtual void ConfigureIoC(IServiceCollection services) { }

    public override object GetInstance(Type type)
    {
        return this.ServiceProvider.GetRequiredService(type);
    }

    protected override void Launch()
    {
        base.DisplayRootView(this.RootViewModel);
    }

    public override void Dispose()
    {
        base.Dispose();

        ScreenExtensions.TryDispose(this._rootViewModel);
        if (this._serviceProvider != null)
        {
            this._serviceProvider.Dispose();
        }
    }
}

然后新建当前项目的 Bootstrapper,在这里可以做一些 View 相关的配置和服务注册。

需要注意的是,如果使用 Stylet 默认的 IOC 容器,会自动收集所有的 View 和 ViewModel,但如果使用其他的 IOC 框架,就丢失了这个能力。

需要自己手动注册服务,如下面的

services.AddSingleton<RootViewModel>();
services.AddSingleton<RootView>();

暂时没有找到快捷的解决方案,可能需要手写一个 Analyzer 来做预编译处理,自动收集并注册依赖。当然,也可以直接使用 autofac 这样的库,但运行时加载的性能不如预编译处理。

详见: 使用 roslyn 的 Source Generator 自动完成依赖收集和注册

public class Bootstrapper : MicrosoftDependencyInjectionBootstrapper<RootViewModel>
{
    protected override void OnStart()
    {
        // This is called just after the application is started, but before the IoC container is set up.
        // Set up things like logging, etc
    }

    protected override void Configure()
    {
        // This is called after Stylet has created the IoC container, so this.Container exists, but before the
        // Root ViewModel is launched.
        // Configure your services, etc, in here
    }

    protected override void ConfigureIoC(IServiceCollection services)
    {
        base.ConfigureIoC(services);
        services.AddSingleton<RootViewModel>();
        services.AddSingleton<RootView>();
    }

    protected override void OnLaunch()
    {
        // This is called just after the root ViewModel has been launched
        // Something like a version check that displays a dialog might be launched from here
    }

    protected override void OnExit(ExitEventArgs e)
    {
        // Called on Application.Exit
    }

    protected override void OnUnhandledException(DispatcherUnhandledExceptionEventArgs e)
    {
        // Called on Application.DispatcherUnhandledException
    }
}

参考

canton7/Stylet: A very lightweight but powerful ViewModel-First MVVM framework for WPF for .NET Framework and .NET Core, inspired by Caliburn.Micro.

如何在WPF项目中使用Hosting管理应用的配置、日志、服务等_哔哩哔哩_bilibili

原文链接:https://www.cnblogs.com/jasongrass/p/18540534

标签:AddSingleton,void,Hosting,override,protected,构建,services,WPF,App
From: https://www.cnblogs.com/jasongrass/p/18540534

相关文章

  • libwebp在windows下构建及编译运行
    因为正在进行WEBP图像的学习,因此有必要对WEBP的官方实现——libwebp进行本地构建和编译,以方便对标准及代码的理解。下面记录一下,在本地Windows电脑上,构建并编译libwebp的过程。步骤一:下载源码首先,获取libwebp的最新源码:从官方Git仓库克隆:gitclonehttps://chromium......
  • 使用LangGraph构建复杂AI工作流:子图架构详解
    一、子图架构概述子图(Subgraph)是LangGraph中一个强大的特性,它允许我们将复杂的工作流程分解成更小、更易管理的组件。通过子图,我们可以实现模块化设计,提高代码的可重用性和可维护性。1.1子图的基本概念子图本质上是一个完整的图结构,可以作为更大图结构中的一个节点使用。它具......
  • wpf combobox绑定到enum
    搜索到这个网页在其中发现了这个方法,比较简单:publicenumRULE{[Description("Любые,безограничений")]any,[Description("Любыееслибудеттривряд")]anyThree,[Descri......
  • wpf项目使用winform控件
    环境:Win10、VS2017一、新建WPF项目  2.WPF项目添加System.Windows.Forms和WindowsFormsIntegration引用  3. 编写WPF窗体代码3.1.头部添加引用1xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"2xmlns:wfi="clr-namespace:S......
  • LangGraph入门:构建ReACT架构的智能Agent
    引言在人工智能和大语言模型(LLM)快速发展的今天,如何构建高效、灵活的智能Agent成为了一个热门话题。LangGraph作为一个强大的工具,为我们提供了一种新的方式来实现复杂的AI工作流,特别是在构建ReACT(ReasoningandActing)架构的智能Agent方面表现出色。本文将深入探讨如何使用LangGra......
  • 使用 .NET Core 7 和 SignalR 构建实时聊天应用程序
    动动你可爱的小手,请关注下本人公众号,继续为您提供更多原创技术文章。谢谢给为的支持SignalR 是一个ASP.NET库,它支持实时Web功能,允许服务器立即将更新推送到客户端,从而提高应用程序的效率和响应能力。它通过简化通信和支持各种传输协议,对于聊天应用程序、实时仪表板和协......
  • wpf中取消按钮的默认样式
    <Stylex:Key="TransparentButton"TargetType="Button"><SetterProperty="Background"Value="Transparent"/><SetterProperty="BorderThickness"Value="0"/><SetterP......
  • 如何在鸿蒙NEXT系统中构建安全的数据防泄漏体系
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在当今数字化时代,数据已成为企业......
  • 智慧医疗领域帮助中心的构建与优化
    大家晚上好,这里是ai元启航,今天这篇分享的文章涉及内容是智慧医疗~智慧医疗的快速发展对内部支持体系提出了更高要求。一个高效、易用的帮助中心,不仅能够提升医护人员的工作效率,还能促进医疗服务的标准化和智能化。本文将分析智慧医疗行业如何构建和优化帮助中心,以提供更好的内部......
  • 法律咨询知识中台的构建策略
    一、引言在数字化转型的推动下,法律咨询行业正面临着前所未有的机遇与挑战。为了更好地提升服务质量,加强知识管理,构建法律咨询知识中台已成为行业的必然选择。本文将探讨法律咨询知识中台的构建策略,旨在为法律服务机构提供有效的知识管理解决方案。二、法律咨询知识中台的定义与......