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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:07:29