MAUI Hybrid应用启动预加载数据:依赖注入服务使用问题
问题描述
我的MAUI Hybrid应用需要在首页面渲染时检查用户登录状态,从而获取用户专属数据。我尝试在App.xaml.cs的CreateWindow事件中执行预加载任务,但此时依赖注入服务似乎无法正常使用。CustomAuthenticationStateProvider是一个重写了AuthenticationStateProvider.GetAuthenticationStateAsync()的服务,用于在Maui SecureStorage存在有效令牌时验证用户身份。请问如何在启动阶段执行可使用依赖注入服务的代码?
App.xaml.cs 代码示例:
public partial class App : Application { [Inject] CustomAuthenticationStateProvider authStateProvider { get; set; } public App() { InitializeComponent(); MainPage = new MainPage(); } protected override Window CreateWindow(IActivationState activationState) { Window window = base.CreateWindow(activationState); window.Created += (s, e) => { _ = PreloadTasks(); }; return window; } public async Task PreloadTasks() { var state = await authStateProvider.GetAuthenticationStateAsync(); if (state.User.Identity.IsAuthenticated) { //preload user specific data while Ui is rendering } } }
Program.cs 代码示例:
builder.Services.AddAuthorizationCore(); builder.Services.AddScoped<CustomAuthenticationStateProvider>(); builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomAuthenticationStateProvider>()); return builder.Build();
问题根源
你代码里的[Inject]属性未生效,因为默认情况下App实例是通过new App()直接创建的,而非由依赖注入容器实例化,导致属性注入逻辑未被触发,authStateProvider会是null。
解决方案
这里提供两种可行的解决方式:
方式一:通过窗口的MauiContext获取服务(无需修改App创建逻辑)
直接在CreateWindow的Created事件中,从窗口的MauiContext获取DI服务,绕过App实例的注入问题:
修改App.xaml.cs的CreateWindow方法:
protected override Window CreateWindow(IActivationState activationState) { Window window = base.CreateWindow(activationState); window.Created += async (s, e) => { // 从窗口的MauiContext获取服务提供者 var services = ((Window)s).Handler.MauiContext.Services; var authStateProvider = services.GetRequiredService<CustomAuthenticationStateProvider>(); var state = await authStateProvider.GetAuthenticationStateAsync(); if (state.User.Identity.IsAuthenticated) { // 在UI渲染的同时预加载用户专属数据 } }; return window; }
这种方式无需改动Program.cs,直接利用窗口初始化后的上下文获取服务,简单高效。
方式二:让App由DI容器实例化(支持属性注入)
修改Program.cs,将App注册为服务并由DI容器创建,使[Inject]属性正常生效:
- 更新
Program.cs:
builder.Services.AddAuthorizationCore(); builder.Services.AddScoped<CustomAuthenticationStateProvider>(); builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomAuthenticationStateProvider>()); // 将App注册为DI服务 builder.Services.AddTransient<App>(); var appBuilder = builder.Build(); // 从DI容器获取App实例并运行 var app = appBuilder.Services.GetRequiredService<App>(); app.Run();
- 保持
App.xaml.cs原有代码不变即可,此时[Inject]的authStateProvider会被DI容器正确注入,PreloadTasks方法能正常调用服务。
注意事项
- 方式一适合快速解决当前问题,无需改动App的创建逻辑;
- 方式二更符合依赖注入设计原则,适合后续需要在App类中使用更多DI服务的场景;
- 你当前用
_ = PreloadTasks();异步执行预加载的方式可以避免阻塞UI渲染,处理得没问题。
内容的提问来源于stack exchange,提问作者Matias Masso
相关产品推荐
相关产品推荐

