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

Mvvm 动态创建对象时避免控制反转的服务定位器,mvvm,dependency-injection,inversion-of-control,service-locator,Mvvm,Dependency Injection,Inversion Of Control,Service Locator,我有一个基于MVVM、Caliburn.Micro和Ninject的WPF应用程序。我有一个名为ShellViewModel的根视图模型。它有两个依赖项(通过构造函数注入),这些依赖项在Caliburn的引导程序中配置。到目前为止还不错 在该行的某个地方,有一个带有几个按钮的MenuViewModel,它依次打开其他具有自己依赖项的ViewModel。这些viewmodels不是在根对象的创建过程中创建的,但我仍然希望从IoC容器向它们注入依赖项 我已经阅读了这个问题,我理解其中的要点 然而,我

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

在该行的某个地方,有一个带有几个按钮的MenuViewModel,它依次打开其他具有自己依赖项的ViewModel。这些viewmodels不是在根对象的创建过程中创建的,但我仍然希望从IoC容器向它们注入依赖项

我已经阅读了这个问题,我理解其中的要点


然而,我的印象是,我的MenuViewModel需要能够访问我的IoC容器,以便正确地注入动态生成的viewmodels。这是我试图避免的。还有别的办法吗?

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

考虑一下,如果没有按需需求,那么显然可以使这些视图模型成为链上的
MenuViewModel
等的依赖项,直到到达对象图的根(“code>ShellViewModel”),容器将连接所有内容

您可以在对象图中放置一个“防火墙”,方法是用能够构造
MenuViewModel
的依赖项的内容替换依赖项本身。容器显然是这项工作的选择,从实际的角度来看,这是一个足够好的解决方案,即使它没有那么纯粹

但你也可以用专用工厂代替集装箱;此工厂将依赖于容器,并为
MenuViewModel
的实际依赖项提供只读属性。访问属性将导致容器解析对象并返回它们(访问器方法也可以代替属性工作;更合适的是完全另一种讨论,所以只要使用您认为更好的方法即可)

看起来您并没有真正改变现状,但是如果
MenuViewModel
直接依赖于容器,情况就不一样了。在这种情况下,通过查看
MenuViewModel
的公共接口,您将不知道它的真正依赖关系是什么,而现在您将看到它依赖于以下内容

interface IMenuViewModelDependencyFactory
{
    public RealDependencyA { get; }
    public RealDependencyB { get; }
}
信息量要大得多。如果你看看concrete
MenuViewModelDependencyFactory的公共界面,情况也会好得多:

class MenuViewModelDependencyFactory : IMenuViewModelDependencyFactory
{
    private Container container;

    public MenuViewModelDependencyFactory(Container container) { ... }

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

对于
MenuViewModelDependencyFactory
打算对容器做什么,不应该有任何混淆,因为它非常专业化。

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

考虑一下,如果没有按需需求,那么显然可以使这些视图模型成为链上的
MenuViewModel
等的依赖项,直到到达对象图的根(“code>ShellViewModel
”),容器将连接所有内容

您可以在对象图中放置一个“防火墙”,方法是用能够构造
MenuViewModel
的依赖项的内容替换依赖项本身。容器显然是这项工作的选择,从实际的角度来看,这是一个足够好的解决方案,即使它没有那么纯粹

但你也可以用专用工厂代替集装箱;此工厂将依赖于容器,并为
MenuViewModel
的实际依赖项提供只读属性。访问属性将导致容器解析对象并返回它们(访问器方法也可以代替属性工作;更合适的是完全另一种讨论,所以只要使用您认为更好的方法即可)

看起来您并没有真正改变现状,但是如果
MenuViewModel
直接依赖于容器,情况就不一样了。在这种情况下,通过查看
MenuViewModel
的公共接口,您将不知道它的真正依赖关系是什么,而现在您将看到它依赖于以下内容

interface IMenuViewModelDependencyFactory
{
    public RealDependencyA { get; }
    public RealDependencyB { get; }
}
信息量要大得多。如果你看看concrete
MenuViewModelDependencyFactory的公共界面,情况也会好得多:

class MenuViewModelDependencyFactory : IMenuViewModelDependencyFactory
{
    private Container container;

    public MenuViewModelDependencyFactory(Container container) { ... }

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

对于
MenuViewModelDependencyFactory
打算如何处理这里的容器,不应该有任何混淆,因为它非常专业化。

我以前已经看到过这种工厂类型的方法,但没有实际指定接口中的依赖项,非常整洁。我以前已经见过这种工厂类型的方法,但实际上没有在接口中指定依赖项,非常整洁。