如何在MAUI生命周期事件中访问依赖注入的Service?
解决MAUI Windows应用启动时通过DI获取数据库服务的问题
我开发一款仅面向Windows的MAUI应用,希望在启动时检查数据库中是否存在特定表。已通过依赖注入(Dependency Injection)注入了管理数据库访问的独立类,但生命周期事件在构建器(builder)内创建,无法通过常规DI方式获取该类。当前代码运行时App.Current和windows参数为空,触发NullReferenceException异常。
当前代码如下:
public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); builder.Services.AddTransient<MainPage>(); builder.Services.AddTransient<MainPageViewModel>(); builder.Services.AddSingleton<IDatabaseAccess, DatabaseAccess>(); builder.ConfigureLifecycleEvents(events => events.AddWindows(windows => windows .OnLaunching((window, args) => { var app = App.Current; using (var serviceScope = App.Current.Handler.MauiContext.Services.GetService<IServiceScopeFactory>().CreateScope()) { var dbAccess = serviceScope.ServiceProvider.GetRequiredService<IDatabaseAccess>(); if (!dbAccess.DoesMappingTableExist()) { dbAccess.InitializeDb(); } } }))); #if DEBUG builder.Logging.AddDebug(); #endif return builder.Build(); } }
解决方案
问题核心是OnLaunching事件触发时机过早,此时应用和窗口实例尚未完成初始化,导致空引用。以下两种方案可解决问题:
方案一:在App类中通过构造注入处理
直接在App的构造函数中注入IDatabaseAccess,此时DI容器已完全初始化,无需依赖生命周期事件:
public partial class App : Application { private readonly IDatabaseAccess _dbAccess; public App(IDatabaseAccess dbAccess) { InitializeComponent(); _dbAccess = dbAccess; // 执行数据库检查与初始化 if (!_dbAccess.DoesMappingTableExist()) { _dbAccess.InitializeDb(); } MainPage = new MainPage(); } }
方案二:使用正确的生命周期事件
若必须依赖Windows生命周期事件,改用OnLaunched事件(启动完成后触发),并直接从构建好的MauiApp实例获取服务:
public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); builder.Services.AddTransient<MainPage>(); builder.Services.AddTransient<MainPageViewModel>(); builder.Services.AddSingleton<IDatabaseAccess, DatabaseAccess>(); // 先构建MauiApp实例 var mauiApp = builder.Build(); // 配置OnLaunched事件,此时窗口已初始化 mauiApp.Services.GetRequiredService<ILifecycleEventService>().AddWindows(windows => windows.OnLaunched((window, args) => { var dbAccess = mauiApp.Services.GetRequiredService<IDatabaseAccess>(); if (!dbAccess.DoesMappingTableExist()) { dbAccess.InitializeDb(); } })); #if DEBUG builder.Logging.AddDebug(); #endif return mauiApp; } }
关键说明
OnLaunching是启动前事件,应用上下文未就绪;OnLaunched是启动完成事件,所有实例已初始化。- 直接通过
mauiApp.Services获取服务,避免依赖未就绪的App.Current。
内容的提问来源于stack exchange,提问作者AracKnight
相关产品推荐
相关产品推荐

