WPF 中引入依赖注入(.NET 通用主机)
WPF 中引入依赖注入(.NET 通用主机)
在网上看到的文章都是通过 App.cs
中修改配置进行的,这样侵入性很高而且服务主机是通过 App
启动时加载的而不是服务主机加载的 App
有一点违反原则。目前,借助 C# 9.0 带来的顶层语句可以轻松解决这个问题。
方案
- 在 nuget 中安装
Microsoft.Extensions.Hosting
- 在根目录新建 Program.cs,改为下面的代码
using TestProgram;
using TestProgram.Common;
// 使用 .NET 依赖注入库
using Microsoft.Extensions.DependencyInjection;
// 使用 .NET 通用主机
using Microsoft.Extensions.Hosting;
using System.Threading;
// 窗口化应用需要在 STA 模式下运行,设置当前
if (!Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA))
{
Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
}
// 构建默认主机
var builder = Host.CreateDefaultBuilder();
// 配置
await builder.ConfigureServices(services =>
{
services.AddLogging();
// 注入 ViewModel(自行实现非官方)
services.AddViewModels();
// 注入 View(自行实现非官方)
services.AddViews();
// 注入 WPF 启动类 App
services.AddSingleton<App>();
// 启动 WPF 服务
services.AddHostedService<WPFRunner<App, MainWindow>>();
}).Build().RunAsync();
- 编写
WPFRunner
用于启动 WPF 服务,在适合的命名空间中新建一个WPFRunner.cs
文件,插入下面的代码
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestProgram.Common
{
public class WPFRunner<TApplication, TWindow> : IHostedService where TApplication : System.Windows.Application where TWindow : System.Windows.Window
{
private readonly TApplication application;
private readonly TWindow window;
public WPFRunner(TWindow window, TApplication application)
{
this.window = window;
this.application = application;
}
// 参考 ASP.NET 中的后台服务(见下方参考)
public Task StartAsync(CancellationToken cancellationToken)
{
// 启动
application.Run(window);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
// 结束
application.Shutdown();
return Task.CompletedTask;
}
}
}