简单的注射器 - 注册集合

时间:2015-10-07 09:43:27

标签: c# mvvm ioc-container simple-injector

我使用Simple Injector创建IoC容器。我在这里采用了模式:

Page Navigation using MVVM in Store App

正如我在上面发表的评论中所说,我想注册INavigationPage的集合。我这样做了:

 private static void RegisterNavigationPages()
 {
        Container.RegisterCollection<INavigationPage>(new []
        {
            typeof(MainNavigationPage),
            typeof(SecondNavigationPage)
        });
 }

在容器内部,我将ViewModels和NavigationService设置为:

Container.Register<INavigationService, NavigationService>(Lifestyle.Singleton);
Container.Register<IMainViewModel, MainViewModel>(Lifestyle.Singleton);
Container.Register<ISecondViewModel, SecondViewModel>(Lifestyle.Singleton);

这是我设置页面的DataContext的方式:

DataContext = App.Container.GetInstance<IMainViewModel>();

一切正常,但我想在ViewModel构造函数中使用该集合中的NavigationPages。我可以通过索引来做到这一点:

 public SecondViewModel(INavigationService navigationService, IEnumerable<INavigationPage> navigationPageCollection)
 {
     NavigationService = navigationService;
     _navigationPage = (navigationPageCollection.ToList())[0];
     GoToMainPageCommand = new Command(GoToMainPageAction);
 }

但它不是优雅的解决方案,因为当我更改NavigationPages的顺序时,我将不得不更改整个应用程序中的所有索引。当我能够识别出我想在ViewModel构造函数中使用哪个NavigationPage时,它是否是任何解决方案?

我无法通过typeof来实现,因为NavigationPage类型在UIProject中,因为循环引用依赖,我无法从ViewModel项目中引用它。

2 个答案:

答案 0 :(得分:4)

目前SecondViewModel的正确性完全取决于navigationPageCollection的顺序和填充,这使得它非常脆弱。如果您的SecondViewModel需要MainNavigationPage,那就是您应该注入的内容。不要注入一个系列;注入页面本身。这可能意味着MainNavigationPage需要自己的界面,例如IMainNavigationPage。这消除了您现在遇到的任何歧义。但是,您可能更好地定义RAP principle,而不是加载一对一映射非通用接口(违反few generic abstractions)。

答案 1 :(得分:0)

我有类似的问题,之前已经解决了这个问题。在这里阅读我的博客 clean factory pattern

基本上你需要的是添加一个方法或属性来识别INavigationPage中的用户,然后在SecondViewModel中添加相同的标识符。 SecondViewModel构造函数只需要迭代IEnumerable并找到它需要的页面。