dependency-injection - 在 Windows 客户端 (WPF) 应用程序中进行依赖注入(inject)的正确方法

标签 dependency-injection ninject service-locator testability thick-client

我习惯于 Web 应用程序中的 IoC/DI - 主要是 Ninject 和 MVC3。我的 Controller 是为我创建的,填充了所有的依赖项、子依赖项等。

但是,在胖客户端应用程序中情况有所不同。我必须创建自己的对象,或者我必须恢复到服务定位器风格的方法,在这种方法中我要求内核(可能通过一些接口(interface),以允许可测试性)给我一个完整的对象与依赖关系。

但是,我已经看到有几个地方将 Service Locator 描述为反模式。

所以我的问题是 - 如果我想在我的胖客户端应用程序中从 Ninject 中受益,有没有更好/更合适的方法来获得这一切?

  • 可测试性
  • 正确的 DI/IoC
  • 尽可能少的耦合

  • 请注意,我在这里讨论的不仅仅是 MVVM 以及将 View 模型放入 View 中。这具体是由需要从内核提供存储库类型对象触发的,然后从该存储库中获取注入(inject)功能的实体(数据当然来自数据库,但它们还需要一些对象作为参数,具体取决于状态世界,Ninject 知道如何提供)。我可以在不将存储库和实体都留下无法测试的困惑的情况下以某种方式做到这一点吗?

    如果有任何不清楚的地方,请告诉我。谢谢!

    编辑 7 月 14 日

    我确信提供的两个答案可能是正确的。然而,我 body 的每一根纤维都在与这种变化作斗争;其中一些可能是由于缺乏知识造成的,但还有一个具体原因使我无法看到这种做事方式的优雅;

    我在最初的问题中没有很好地解释这一点,但问题是我正在编写一个库,该库将被几个(最初是 4-5 个,以后可能更多)WPF 客户端应用程序使用。这些应用程序都在相同的域模型等上运行,因此将它们全部保存在一个库中是保持 DRY 的唯一方法。然而,这个系统的客户也有可能编写他们自己的客户——我希望他们有一个简单、干净的库可以与之交谈。我不想强制他们在他们的 Composition Root 中使用 DI(在他的书中使用 Mark Seeman 之类的术语)——因为与他们刚刚更新 MyCrazySystemAdapter() 并使用它相比,这使事情变得非常复杂。

    现在,MyCrazySystemAdapter(之所以选择这个名字是因为我知道人们在这里会不同意我的观点)需要由子组件组成,并使用 DI 组合在一起。 MyCrazySystemAdapter 本身不需要注入(inject)。它是客户端与系统对话时需要使用的唯一接口(interface)。因此,客户应该高兴地获得其中之一,DI 就像幕后发生的魔术一样,并且该对象由许多不同的对象使用最佳实践和原则组成。

    我确实意识到这将是一种有争议的做事方式。但是,我也知道将成为此 API 客户的人。如果他们发现他们需要学习和连接 DI 系统,并提前在他们的应用程序入口点(Composition Root)中创建他们的整个对象结构,而不是新建一个对象,他们会给我中指和直接弄乱数据库并以您难以想象的方式搞砸事情。

    TL;DR:提供结构合理的 API 对客户来说太麻烦了。我的 API 需要交付他们可以使用的单个对象——使用 DI 和适当的实践在幕后构建。现实世界有时会胜过将所有东西倒过来以忠于模式和实践的愿望。

    最佳答案

    我建议看看像 Caliburn 这样的 MVVM 框架。它们提供与 IoC 容器的集成。

    基本上,您应该在 app.xaml 中构建完整的应用程序。如果某些部分需要稍后创建,因为您还不知道在启动时创建它们的所有内容,则将工厂作为接口(interface)(见下文)或 Func(见 Does Ninject support Func (auto generated factory)?)注入(inject)需要创建此实例的类中。两者都将在下一个 Ninject 版本中得到原生支持。

    例如

    public interface IFooFactory { IFoo CreateFoo(); }
    public class FooFactory : IFooFactory
    {
        private IKernel kernel;
        FooFactory(IKernel kernel)
        {
            this.kernel = kernel;
        }
    
        public IFoo CreateFoo()
        {
            this.kernel.Get<IFoo>();
        }
    }
    

    请注意,工厂实现在逻辑上属于容器配置,而不是业务类的实现。

    关于dependency-injection - 在 Windows 客户端 (WPF) 应用程序中进行依赖注入(inject)的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6634588/

    相关文章:

    java - Grails 与另一个 Spring 应用程序的集成 - 数据源过载

    php - 如何在 Laravel 4 中注入(inject)多个共享相同接口(interface)的类

    architecture - 简单的注入(inject)器和内部构造函数

    c# - Ninject 根据顶级项目获得不同实现的最佳实践

    c# - 在 Ninject 中是否允许将 IKernel 注入(inject)到一些地方?

    c# - 包装 API 以支持依赖注入(inject)

    c# - 如何将实例 ninject 传递到构造函数中

    php - 具有依赖项的可测试 Controller

    具有多模块 Maven 项目的 GWT ServiceLocator

    unit-testing - 可以为普遍使用的依赖项使用服务定位器吗?