前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >使用 Hosting 构建 WPF 程序 - Stylet 篇

使用 Hosting 构建 WPF 程序 - Stylet 篇

作者头像
jgrass
发布2024-12-25 18:26:00
发布2024-12-25 18:26:00
6000
代码可运行
举报
文章被收录于专栏:蔻丁杂记蔻丁杂记
运行总次数:0
代码可运行

.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 添加引用

代码语言:javascript
代码运行次数:0
复制
// 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。

代码语言:javascript
代码运行次数:0
复制
// csproj  <ItemGroup>    <ApplicationDefinition Remove="App.xaml" />    <Page Include="App.xaml" />  </ItemGroup>

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

代码语言:javascript
代码运行次数:0
复制
// 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 相关的服务,如配置,日志等。

代码语言:javascript
代码运行次数:0
复制
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

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

代码语言:javascript
代码运行次数:0
复制
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 框架,就丢失了这个能力。

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

代码语言:javascript
代码运行次数:0
复制
services.AddSingleton<RootViewModel>();services.AddSingleton<RootView>();

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

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

代码语言:javascript
代码运行次数:0
复制
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://cloud.tencent.com/developer/article/2481574

本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024年11月1日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 添加引用
  • 2 修改 App.xaml
  • 3 App.xaml.cs
  • 4 Stylet Bootstrapper
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档