wpf - 使用 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());
}
问题
- 当我导航到 ActivityManagement 视图时,它总是使用最后一个注册的具体类作为 IActivityService 注入 ActivityManagementViewModel。为什么会这样?
- 如何在运行时使用选择的具体类导航到视图?
我之所以要这样做是因为视图 UI 和要求对于界面的每个具体实现都是完全相同的。不同之处在于具体类使用的数据和数据存储库。对我来说,为每个具体实现重新创建相同的视图和视图模型以以相同的方式显示数据是没有意义的。当引入新的具体实现时,总是必须添加它们也不是一件好事。
如果我遗漏了什么或者有更好的方法来实现这一点,请教育我。
解决方案
当你用同一接口注册多个类型而不命名时,最后一个通过覆盖前面的来获胜。如果使用命名注册,则只有命名注册,没有默认注册,因此在解析视图模型时会出错。
如何在运行时使用选择的具体类导航到视图?
我会创建一个工厂并注入它,例如:
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();
}
}
}
然后在视图模型中解析活动服务。根据需要调整工厂,例如产品或单件产品的各种参数。这里邪恶但合理的可能是将容器简单地注入工厂。
推荐阅读
- hybris - SAP HYBRIS - 将 backoffice-config.xml 拆分为多个 xml
- python - 字典包含在字典中的列表中
- hadoop - 编写 Flume 配置以将不断增长的文件上传到 HDFS
- java - 如何对 EJB3 事务提交或回滚做出反应?
- python-3.x - Python 无法从 Visual Studio 代码或原子运行到文本文件,但使用崇高文本写入
- php - 路由内部的 Laravel app()->getLocale() 总是打印默认的“en”
- javascript - 克隆斑马日期选择器移动图标
- npm - 为 Vue JS 项目构建 dist 文件夹
- hive - HIVE 长小数结果
- r - 如何用r中的名称列表重命名多个文件的特定列?