UWP进程内后台任务使用Prism的依赖注入

Prism是一个可用于UWP平台的MVVM库,提供了包括依赖注入在内的实用功能。在使用过程中,发现如果要在UWP的进程内后台任务中使用Prism的依赖注入功能,需要对一些初始化进行一些修改。

UWP的进程内后台任务的入口点是App类的OnBackgroundActivated函数。如果你的应用的App类继承了PrismUnityApplication或者其他的PrismApplication类,那么试图在OnBackgroundActivated中使用Container属性时,可能出现NullReferenceException错误。更坑爹的是,如果你在Visual Studio中启动调试后再触发后台任务,是不会出现这个错误的,但当前台应用没有启动时,后台任务将会100%触发NullReferenceException。

下面这样的实现会导致后台任务永远不能正常运行,除非前台应用已经事先启动:

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    base.OnBackgroundActivated(args);
    var deferral = args.TaskInstance.GetDeferral();
    // 下面这行会触发NullReferenceException
    await Container.Resolve<BackgroundNuGetCleanerService>().RunAsync();
    deferral.Complete();
}

原因是因为,Prism Unity 6.3.0版本并没有对进程内后台任务作优化。
OnBackgroundActivated函数并不会触发Prism的初始化过程。为了解决这个问题,需要在
OnBackgroundActivated的开头调用CreateAndConfigureContainer函数,手动触发Prism依赖注入容器的初始化:

protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
    base.OnBackgroundActivated(args);

    // 先初始化Container
    CreateAndConfigureContainer();

    var deferral = args.TaskInstance.GetDeferral();
    // 下面这行会触发NullReferenceException
    await Container.Resolve<BackgroundNuGetCleanerService>().RunAsync();
    deferral.Complete();
}

为了避免重复创建容器,我们还需要重写App.CreateAndConfigureContainer函数,增加是否已经初始化的判断:

protected override void CreateAndConfigureContainer()
{
    if (Container == null)
    {
        base.CreateAndConfigureContainer();
    }
}

以上写法已应用于“NuGet缓存清理器”应用并经过测试。其源代码可从GitHub上获取:App.xaml.cs

留言

有想法?请给我们留言!您的留言不会直接显示在网站内。