首页 > 解决方案 > 使用 Prism 7 的 WPF 应用程序:如何使用具有多个具体类的接口为 VM 注册和导航

问题描述

我正在使用 Prism 7 创建 WPF 应用程序。在其中一个视图模型中,我试图注入一个名为 IActivityService 的接口。IActivityService 有多个具体类,但出于问题的目的,TestActivtyService 和ExerciseActivityService。以下是我让他们注册的方式:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
      containerRegistry.Register<IActivityService, TestActivtyService>(InstanceNames.TestActivtyService);
      containerRegistry.Register<IActivityService, ExerciseActivityService>(InstanceNames.ExerciseActivityService);

      containerRegistry.RegisterForNavigation<Shell, ShellViewModel>(ViewNames.Shell);
      containerRegistry.RegisterForNavigation<Home, HomeViewModel>(ViewNames.Home);
      containerRegistry.RegisterForNavigation<ActivityManagement, ActivityManagementViewModel>(ViewNames.TestManagement);
}

ActivityManagementViewModel 有一个使用 IActivityService 的构造函数。

private readonly IActivityService _activityService;

public ActivityManagementViewModel(IRegionManager regionManager, IActivityService activityService)
    : base(regionManager)
{
    this._activityService = activityService;
}

我无法导航到使用 ActivityManagementViewModel 的 ActivityManagement 视图。

private void NavigateToTesting()
{
    //Navigate to ActivityManagement with TestActivtyService injected as IActivityService
    RegionManager.RequestNavigate(RegionNames.MainRegion, ViewNames.ActivityManagement.GetUri());
}

private void NavigateToExercise()
{
    //Navigate to ActivityManagement with ExerciseActivityService injected as IActivityService
    RegionManager.RequestNavigate(RegionNames.MainRegion, ViewNames.ActivityManagement.GetUri());
}

问题

  1. 当我导航到 ActivityManagement 视图时,它总是使用最后一个注册的具体类作为 IActivityService 注入 ActivityManagementViewModel。为什么会这样?
  2. 如何在运行时使用选择的具体类导航到视图?

我之所以要这样做是因为视图 ​​UI 和要求对于界面的每个具体实现都是完全相同的。不同之处在于具体类使用的数据和数据存储库。对我来说,为每个具体实现重新创建相同的视图和视图模型以以相同的方式显示数据是没有意义的。当引入新的具体实现时,总是必须添加它们也不是一件好事。

如果我遗漏了什么或者有更好的方法来实现这一点,请教育我。

标签: wpfdependency-injectionprismunity-containerprism-7

解决方案


当你用同一接口注册多个类型而不命名时,最后一个通过覆盖前面的来获胜。如果使用命名注册,则只有命名注册,没有默认注册,因此在解析视图模型时会出错。

如何在运行时使用选择的具体类导航到视图?

我会创建一个工厂并注入它,例如:

internal class ActivityServiceFactory : IActivityServiceFactory
{
    public IActivityService Create( ActivityServiceType activityServiceType )
    {
        switch (activityServiceType)
        {
            case ActivityServiceType.Test: return new TestActivtyService();
            case ActivityServiceType.Exercise: return new ExerciseActivityService();
            default: throw new IllegalArgumentException();
        }
    }
}

然后在视图模型中解析活动服务。根据需要调整工厂,例如产品或单件产品的各种参数。这里邪恶但合理的可能是将容器简单地注入工厂。


推荐阅读