【问题标题】:Avoiding the service locator with inversion of control while dynamically creating objects在动态创建对象时避免使用控制反转的服务定位器
【发布时间】:2012-05-15 10:53:12
【问题描述】:

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

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

我在service locator vs dependency injection 上阅读了这个问题,我理解所提出的观点。

我的印象是,我的 MenuViewModel 需要能够访问我的 IoC 容器才能正确注入动态制作的视图模型……这是我试图避免的事情。还有其他方法吗?

【问题讨论】:

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


    【解决方案1】:

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

    考虑一下,如果没有按需需求,那么显然您可以使这些视图模型成为 MenuViewModel 的依赖项,依此类推,直到您到达对象图的根(ShellViewModel)和容器会将所有东西连接起来。

    您可以在对象图中放置一个“防火墙”,方法是用可以构造MenuViewModel 的依赖关系的东西代替依赖关系本身。容器是这项工作的明显选择,恕我直言,从实际的角度来看,这是一个足够好的解决方案,即使它不是那么纯净。

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

    看起来你并没有真正改变现状,但如果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 打算在这里对容器做什么应该没有混淆,因为它非常专业化。

    【讨论】:

    • 我之前已经看到过这种工厂类型的方法,但实际上并没有在接口中指定依赖关系,非常简洁。
    猜你喜欢
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 2011-09-15
    • 2017-01-15
    • 1970-01-01
    相关资源
    最近更新 更多