You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Avalonia中实现依赖注入及多视图与视图模型注册方法

在Avalonia中实现类似MAUI的多视图多ViewModel依赖注入(搭配MVVM Community Toolkit)

你当前代码的核心问题是创建了两个独立的ServiceCollection和ServiceProvider,导致依赖无法共享,且未正确让Avalonia框架使用你的DI容器解析视图,因此构造函数注入不生效。以下是适配Avalonia的正确实现方案:

步骤1:统一注册所有服务、ViewModel与视图

不要拆分多个ServiceCollection,将所有依赖注册到同一个集合中,同时注册视图(Avalonia需要通过DI容器解析视图才能自动注入构造函数依赖)。

修改你的ServiceCollectionExtensions:

using incomeExpensTrckAVALONIA.ViewModels;
using incomeExpensTrckAVALONIA.Views;
using Microsoft.Extensions.DependencyInjection;

namespace incomeExpensTrckAVALONIA
{
    public static class ServiceCollectionExtensions
    {
        public static void AddAppServices(this IServiceCollection collection)
        {
            // 注册ViewModel,根据业务需求选择生命周期(Transient/Singleton/Scoped)
            collection.AddTransient<MainViewModel>();
            collection.AddSingleton<ExpensePageViewModel>();
            
            // 注册视图,让Avalonia通过DI解析视图并自动注入依赖
            collection.AddTransient<MainWindow>();
            collection.AddTransient<ExpensePageView>();
            
            // 在此添加其他业务服务,例如数据访问、API服务等
            // collection.AddSingleton<IMyDataService, MyDataService>();
        }
    }
}

步骤2:配置Avalonia关联DI容器

在App类中创建单个ServiceCollection,注册所有服务后构建ServiceProvider,并关联到Avalonia的Locator,让框架自动使用DI解析视图与依赖。

修改App类:

using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using incomeExpensTrckAVALONIA.Views;
using Microsoft.Extensions.DependencyInjection;
using Avalonia.Controls;

namespace incomeExpensTrckAVALONIA;

public partial class App : Application
{
    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
    }

    public override void OnFrameworkInitializationCompleted()
    {
        // 移除Avalonia自带数据验证,避免与MVVM Community Toolkit重复
        BindingPlugins.DataValidators.RemoveAt(0);

        // 注册所有应用服务
        var services = new ServiceCollection();
        services.AddAppServices();
        
        // 构建ServiceProvider
        var serviceProvider = services.BuildServiceProvider();
        
        // 将ServiceProvider绑定到Avalonia Locator,让框架使用DI解析视图
        Locator.CurrentMutable.BindToServiceProvider(serviceProvider);

        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            // 通过ServiceProvider解析MainWindow,自动注入ViewModel到构造函数
            desktop.MainWindow = serviceProvider.GetRequiredService<MainWindow>();
            
            // 若需在MainWindow中导航到ExpensePageView,同样通过DI解析:
            // var expenseView = serviceProvider.GetRequiredService<ExpensePageView>();
            // desktop.MainWindow.Content = expenseView;
        }
        else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
        {
            // 单视图场景下通过DI解析视图
            singleViewPlatform.MainView = serviceProvider.GetRequiredService<ExpensePageView>();
        }

        base.OnFrameworkInitializationCompleted();
    }
}

步骤3:视图的构造函数注入(与MAUI一致)

视图代码可以和MAUI保持几乎一致,直接在构造函数中接收ViewModel并设置为DataContext:

using incomeExpensTrckAVALONIA.ViewModels;
using Avalonia.Controls;

namespace incomeExpensTrckAVALONIA.Views;

public partial class ExpensePageView : UserControl
{
    public ExpensePageView(ExpensePageViewModel expensePageViewModel)
    {
        InitializeComponent();
        DataContext = expensePageViewModel;
    }
}

MainWindow的实现类似:

using incomeExpensTrckAVALONIA.ViewModels;
using Avalonia.Controls;

namespace incomeExpensTrckAVALONIA.Views;

public partial class MainWindow : Window
{
    public MainWindow(MainViewModel mainViewModel)
    {
        InitializeComponent();
        DataContext = mainViewModel;
    }
}

关键注意点

  • 所有依赖必须注册到同一个ServiceCollection,确保依赖关系可共享。
  • 必须将ServiceProvider绑定到Avalonia的Locator,否则框架无法自动使用DI解析视图。
  • 视图必须通过serviceProvider.GetRequiredService<T>()获取,而非手动new,才能触发构造函数注入。

内容的提问来源于stack exchange,提问作者BaselE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:18:13