C# Avalonia如何使用依赖注入 Avalonia DI框架集成教程

4次阅读

Avalonia 使用 .net 原生 microsoft.Extensions.DependencyInjection 实现依赖注入,通过 appBuilder.ConfigureServices 注册服务,并在 ViewModel 或必要组件中通过构造函数注入;不推荐在 View 中直接注入业务服务,应交由 ViewModel 处理。

C# Avalonia如何使用依赖注入 Avalonia DI框架集成教程

在 Avalonia 中使用依赖注入(DI)和 .NET 原生的 Microsoft.Extensions.DependencyInjection 是标准做法,Avalonia 本身不提供独立的“DI 框架”,而是无缝集成 .NET 的通用主机(Generic Host)和 DI 容器。关键在于正确配置 AppBuilder,将服务注册到容器,并在视图、视图模型或控件中通过构造函数注入。

注册服务到 Avalonia DI 容器

Avalonia 应用启动时通过 AppBuilder 配置服务。你应在 Program.cs 中调用 UseStartup() 或直接使用 SetupWithoutStarting() + 手动构建主机,推荐前者以保持与 .NET 主机模式一致。

示例(.NET 6+,使用 AppBuilder):

// Program.cs using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Microsoft.Extensions.DependencyInjection;  class Program {     [STAThread]     public static void Main(string[] args)     {         BuildAvaloniaApp()             .StartWithClassicDesktopLifetime(args);     }      public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure()         .UsePlatformDetect()         .LogToTrace()         .UseReactiveUI()         .SetupWithoutStarting() // 先不启动,以便配置 DI         .ConfigureServices((ctx, services) =>         {             // 注册你的服务(瞬态、作用域、单例)             services.AddSingleton();             services.AddScoped();             services.AddTransient();              // 可选:注册 Avalonia 相关服务(如窗口管理器)             services.AddSingleton();         }); }

在 ViewModel 中使用构造函数注入

Avalonia 的 ViewModel 默认由 DI 容器解析(前提是你在 XAML 中启用了自动绑定或手动指定 DataContext)。只要 ViewModel 类型已注册,且其构造函数参数都能被容器解析,就能自动注入。

  • 确保 ViewModel 在 ConfigureServices 中注册(如 ScopedTransient
  • XAML 中不要硬编码 DataContext,改用 ViewModel={Binding} 或依赖 Locator
  • 推荐使用 Locator 模式(reactiveUI 或自定义)统一管理 ViewModel 生命周期

例如:

public partial class Mainwindow : Window {     public MainWindow()     {         InitializeComponent();         // 若未设置 DataContext,Avalonia 会尝试从 DI 容器解析 MainViewModel         // (需启用 ReactiveUI 或自定义 Locator)     } }

在 View 或 UserControl 中注入服务

View(如 WindowUserControl)本身**不建议直接注入业务服务**,但可在构造函数中注入生命周期短的服务(如 IWindowManagerIDialogService),前提是这些服务已在容器中注册且是 TransientScoped

  • View 构造函数支持注入,但仅限于 Avalonia 启动后容器已就绪的场景(即 SetupWithoutStarting + Start 流程)
  • 避免在 View 中注入耗时或跨生命周期的服务(如数据库上下文),应交由 ViewModel 处理
  • 若需在 View 中获取服务,也可通过 Application.Current?.Services.GetService()(不推荐,破坏测试性)

配合 ReactiveUI 使用更自然的 DI

如果你使用 ReactiveUI(Avalonia 官方推荐组合),可借助 WhenActivatedLocator 实现更清晰的依赖管理:

  • Locator.CurrentMutable.RegisterConstant(...) 注册服务(适合全局单例)
  • ViewModel 继承 ReactiveObject 并在构造函数接收依赖,ReactiveUI 自动参与 DI 解析
  • App.OnFrameworkInitializationCompleted 中初始化 Locator,与 IServiceProvider 对齐

简单对齐方式:

// App.xaml.cs public override void OnFrameworkInitializationCompleted() {     if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)     {         // 将 IServiceProvider 注入 ReactiveUI Locator         Locator.CurrentMutable.InitializeSplat();         Locator.CurrentMutable.InitializeReactiveUI();         Locator.CurrentMutable.Register(() => Application.Current!.Services.GetRequiredService(), typeof(IDataService));     }     base.OnFrameworkInitializationCompleted(); }

基本上就这些。Avalonia 的 DI 不复杂但容易忽略 Setup 顺序和生命周期匹配——重点是用好 ConfigureServices,把服务注册清楚,再让 ViewModel 或必要组件通过构造函数自然消费。不需要引入第三方 DI 框架,.NET 原生容器完全够用。

text=ZqhQzanResources