【问题标题】:General IoC practice - is it wrong for services to depend on each other?一般 IoC 实践 - 服务相互依赖是错误的吗?
【发布时间】:2012-02-13 18:11:27
【问题描述】:

现在我有一些服务定义在不依赖于 IoC 容器的程序集中(在我的例子中是 Ninject)。在主项目中,我有一个 IRepository 用于在容器中注册的数据访问。

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>();

我还注册了 IAuthenticationService 和 IErrorLogger 服务,我希望将存储库用于其逻辑的具体实现。但是,我不确定如何最好地做到这一点。目前,我在两个具体实现上的构造函数都采用 IRepository 参数,并在注册它们时将其传入:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>().
                WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository());

这里我只是告诉容器抓取 IRepository 实例并将其传递给构造函数。

我觉得让我的服务程序集依赖于 ninject 甚至是通用服务定位器 (CSL) 是不对的,但我也不确定我目前的方式。我正在寻找意见和替代解决方案。

如果我的其他服务不使用 IRepository,我将不得不为每种类型的底层 IRepository 类型创建这些服务的新具体实现(例如,用于假数据和真实数据的 AuthenticationService)。这将是大量的逻辑重复。

【问题讨论】:

    标签: c# asp.net-mvc dependency-injection inversion-of-control ninject


    【解决方案1】:

    您的服务程序集不应依赖于 Ninject,而应仅依赖于您为其注册具体类型的接口。 IoC 容器应该只是将依赖项注入类的聚合根。另一方面,包含聚合根 / Ninject 内核的程序集将取决于所有包含具体类型的程序集(否则它如何能够解析它们?)。

    一般而言,对于 IoC,您应该在此处应用 Hollywood principle - 您应该 依赖项赋予您的具体对象实例(尽可能使用构造函数注入),而不是让对象实例 询问他们的依赖关系。

    实际上根本不需要您用于WithConstructorArgument() 的示例,因为依赖解析是递归工作的:您已经向容器注册了IRepositoryIAuthenticationService,因此它知道如何解决这两个问题。因为IAuthenticationService 绑定到AuthenticationService,所以不需要指定构造函数参数,因为它是IRepository 类型并且会自动解析。

    至于重复 - 当然,您必须为 IRepository 为不同的存储库类型创建不同的实现,假设您想要这些存储库的不同的行为。 p>

    【讨论】:

    • 很好的信息!你是对的,我根本不需要指定 WithConstructorArgument。它们是自动注入的。另一个问题是,如果我注册 2 个 IRepository 实现,每个都有不同的名称会怎样。然后我想指定要注入的那个。我知道 Ninject 有一个 NamedAttribute,但是为了避免向我的服务程序集添加 Ninject 依赖项,我不想使用它。那么在这种情况下手动指定将是要走的路吗?仅供参考,我重复关注的不是 IRepository,而是其他服务类。
    • 对于 Ninject,您可以使用 WhenInjectedInto&lt;Foo&gt;(),其中 Foo 是您的服务类。通常,您只会注册存储库的一个具体实现 - 用于伪造数据和测试的实现不应注册为主应用程序的一部分,只能在单独的测试容器中注册
    猜你喜欢
    • 2016-07-22
    • 2021-05-12
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    相关资源
    最近更新 更多