在动态创建对象时避免服务定位器反转控制

时间:2012-05-06 19:23:56

标签: mvvm dependency-injection inversion-of-control service-locator

我有一个基于MVVM的WPF应用程序,Caliburn.Micro和Ninject。我有一个名为ShellViewModel的根视图模型。它有一些依赖项(通过构造函数注入),这些依赖项在Caliburn的Bootstrapper中配置。到目前为止一切都很好。

在某个地方,有一个带有几个按钮的MenuViewModel,它们依次打开其他具有自己依赖关系的视图模型。这些视图模型不是在创建根对象期间创建的,但我仍然希望从IoC容器中将依赖项注入其中。

我已经在service locator vs dependency injection上阅读了这个问题,我理解了要点。

我的印象是,我的MenuViewModel需要能够访问我的IoC容器才能正确注入动态制作的视图模型。这是我试图避免的。还有另一种方式吗?

1 个答案:

答案 0 :(得分:1)

是的,我相信你可以做得更好一些。

如果没有按需要求,那么显然你可以让那些视图模型成为MenuViewModel的依赖关系,依此类推,直到你到达对象图的根(ShellViewModel容器会将所有东西连接起来。

您可以通过替换可以为依赖项本身构建MenuViewModel依赖项的内容,在对象图中放置“防火墙”。容器是这项工作的明显选择,从实用的角度来看,恕我直言这是一个很好的解决方案,即使它不是那么纯粹。

但您也可以替换特殊用途的工厂而不是容器;此工厂将依赖于容器,并为MenuViewModel真实依赖项提供只读属性。访问属性会导致容器解析对象并返回它们(访问器方法也可以工作而不是属性;更合适的是另一个完全讨论,所以只需使用你认为更好的任何东西)。

看起来你可能没有真正改变现状,但情况与MenuViewModel直接依赖容器时的情况不同。在这种情况下,通过查看它的公共接口你不知道MenuViewModel的真正依赖性是什么,而现在你会发现它依赖于像

这样的东西。
interface IMenuViewModelDependencyFactory
{
    public RealDependencyA { get; }
    public RealDependencyB { get; }
}

信息更丰富。如果你看一下具体MenuViewModelDependencyFactory的公共界面,事情也会好得多:

class MenuViewModelDependencyFactory : IMenuViewModelDependencyFactory
{
    private Container container;

    public MenuViewModelDependencyFactory(Container container) { ... }

    public RealDependencyA { get { ... } }
    public RealDependencyB { get { ... } }
}

对于MenuViewModelDependencyFactory打算在这里容器做什么应该没有混淆,因为它非常专业。