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

如何在Xamarin Forms应用中实现构造函数注入?

你遇到的View和ViewModel要求无参构造的核心原因是:默认Xamarin.Forms的页面、ViewModel创建逻辑是通过反射直接调用无参构造实现的,你之前尝试的各类IoC容器本身没有问题,缺少的是容器接管页面和ViewModel创建的逻辑,没有这一步容器根本没有机会介入注入依赖。

下面是适配Microsoft MVVM Toolkit、极简的实现方案:

第一步:安装必要NuGet包

只需要安装两个官方包即可:

  • CommunityToolkit.Mvvm (即Microsoft MVVM Toolkit)
  • Microsoft.Extensions.DependencyInjection (微软官方轻量DI容器)

第二步:配置全局DI容器

在App.xaml.cs中添加容器配置逻辑,所有服务、ViewModel、页面都需要提前注册到容器中:

public partial class App : Application
{
    // 全局DI容器入口
    public static IServiceProvider ServiceProvider { get; private set; }

    public App()
    {
        InitializeComponent();

        // 初始化容器配置
        var serviceCollection = new ServiceCollection();
        
        // 1. 注册业务服务
        serviceCollection.AddSingleton<ITest, TestService>();
        
        // 2. 注册所有ViewModel
        serviceCollection.AddTransient<AboutViewModel>();
        serviceCollection.AddTransient<MainViewModel>();
        
        // 3. 注册所有页面
        serviceCollection.AddTransient<AboutPage>();
        serviceCollection.AddTransient<MainPage>();

        // 构建容器
        ServiceProvider = serviceCollection.BuildServiceProvider();

        // 首页从容器中获取,不要直接new
        MainPage = new NavigationPage(ServiceProvider.GetRequiredService<MainPage>());
    }
}

第三步:实现构造注入

你写的示例AboutViewModel代码无需任何修改,容器会自动解析构造函数的ITest参数:

public class AboutViewModel : ObservableObject
{
    public AboutViewModel(ITest testService)
    {
        Title = "About";
        OpenWebCommand = new AsyncRelayCommand(async () => 
            await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));
        // 注入的testService可以直接使用
        testService.Test();
    }

    public ICommand OpenWebCommand { get; }
}

public interface ITest
{
    void Test();
}

public class TestService : ITest
{
    public void Test()
    {
        Debug.WriteLine("Test successful");
    }
}

第四步:页面绑定逻辑

页面也支持构造注入,直接将注入的ViewModel赋值给BindingContext即可,无需在XAML中硬编码绑定上下文:

public partial class AboutPage : ContentPage
{
    // 构造函数直接注入对应ViewModel
    public AboutPage(AboutViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

页面跳转注意事项

所有页面跳转都要从容器中获取页面实例,不要直接new页面:

// 示例:在MainViewModel中跳转到AboutPage
public ICommand GoToAboutCommand { get; } = new AsyncRelayCommand(async () =>
{
    var aboutPage = App.ServiceProvider.GetRequiredService<AboutPage>();
    await Application.Current.MainPage.Navigation.PushAsync(aboutPage);
});

常见避坑说明

  1. 不要给页面和ViewModel留无参构造,避免误调用默认创建逻辑
  2. 如果你使用Shell路由,只需自定义Shell的内容解析逻辑,从容器中获取对应页面实例即可,整体逻辑一致
  3. MVVM Toolkit的所有功能(如ObservableObject、RelayCommand等)和这套DI逻辑完全解耦,可正常使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 08:54:07