如何在.NET MAUI应用中使用内置DI?注入报错问题排查
问题分析与解决方案
问题根源
- 页面未注册到DI容器:仅注册了
TodoViewModel,但Shell导航时需从DI容器获取页面实例才能自动注入构造函数依赖,未注册页面会导致框架尝试用无参构造创建实例,触发报错。 - 构造函数缺失
InitializeComponent()调用:XAML页面的部分类必须通过该方法加载XAML布局,缺失会导致UI无法渲染,同时框架无法正确识别页面结构。 - Shell导航未适配DI解析逻辑:直接通过
nameof(Page)导航时,Shell默认反射创建无参实例,不会走DI容器的实例化流程。
修复步骤
1. 补全页面构造函数的核心初始化代码
修改TodoPage构造函数,添加InitializeComponent()调用(XAML页面必备):
namespace Todo.Views; public partial class TodoPage : ContentPage { public TodoPage(ViewModels.TodoViewModel viewModel) { InitializeComponent(); // 必须添加此行,加载XAML布局 BindingContext = viewModel; } private async void Add_Todo_Clicked(object sender, EventArgs e) { await Shell.Current.GoToAsync(nameof(AddTodoPage)); } }
2. 将页面注册到DI容器
在MauiProgram.cs的ConfigureServices方法中,把页面与ViewModel一起注册为Transient生命周期:
private static void ConfigureServices(IServiceCollection services) { services.AddTransient<TodoViewModel>(); services.AddTransient<TodoPage>(); // 注册TodoPage到DI容器 services.AddTransient<AddTodoPage>(); // 同步注册AddTodoPage }
3. 配置Shell路由(推荐显式注册)
在AppShell.xaml中注册路由,确保Shell导航时从DI容器获取页面实例:
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:views="clr-namespace:Todo.Views" x:Class="Todo.AppShell"> <!-- 注册页面路由 --> <ShellContent Route="TodoPage" ContentTemplate="{DataTemplate views:TodoPage}" /> <ShellContent Route="AddTodoPage" ContentTemplate="{DataTemplate views:AddTodoPage}" /> </Shell>
4. 保持导航逻辑的一致性
导航时使用路由名称(与注册的Route值匹配),确保Shell通过DI解析实例:
await Shell.Current.GoToAsync(nameof(TodoPage));
关于属性注入失败的说明
MAUI默认DI容器不支持属性注入,且若页面是Shell通过反射无参构造创建的,容器完全未参与实例化过程,自然无法完成属性注入。只有让DI容器负责页面实例的创建(即注册页面到DI),才能实现依赖注入。
内容的提问来源于stack exchange,提问作者Kirk Friend
相关产品推荐
相关产品推荐

