c# - 通过构造函数在 IoC 中强制执行依赖项?

标签 c# interface dependency-injection inversion-of-control abstract-class

我正在尝试接受使用 IoC/依赖注入(inject),同时根据契约(Contract)而不是特定类进行编程。我面临的困境是:

  1. 为 IoC 的接口(interface)编写程序:我开始时 IoC 非常依赖接口(interface)。从 Spring 的示例项目来看,接口(interface)是使用 IoC 进行契约编程的方式。

  2. ( ... 尽管通常首选抽象类:the main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs )

  3. 通过构造函数使类依赖显式化 我的直觉是,将依赖项传递给类的构造函数是一种很好的编程习惯。事实上,这依赖注入(inject)。

  4. ...除非您不能在接口(interface)/抽象类中强制执行构造函数签名:接口(interface)或抽象类都不允许定义构造函数签名( easily / elegantly ) . 另见 Framework Design Guidelines section 4.4: 不要在抽象类型中定义公共(public)或 protected 内部构造函数。 ...仅当用户需要创建该类型的实例时,构造函数才应公开。

这个问题与之前的 stackoverflow 问题有关:Interface defining a constructor signature?

但我的问题是:

由于您不能在 C# 接口(interface)/抽象类中定义构造函数,正如上面的问题所问,在实际层面上:

您如何将此与 passing dependencies in via a constructor 的明智做法相协调? ?

编辑:感谢您的回答。我希望了解在这种情况下我应该做什么。只是不使用构造函数参数?使用某种确实采用依赖项的 Init() 方法? Edit2:感谢您的出色回答,非常有帮助。

最佳答案

我一直认为用(编造的)示例更容易解释...

假设您有一个 ICustomerRepository 接口(interface)、一个 IShoppingCartRepository 接口(interface)和一个 ICheckout 接口(interface)。您具有这些接口(interface)的具体实现 - CustomerRepository、ShoppingCartRepository 和 CheckoutService。

您的 CheckoutService 具体类有一个采用 ICustomerRepository 和 IShoppingCartRepository 的构造函数 - 例如

public CheckoutService(ICustomerRepository customerRepository, IShoppingCartRepository shoppingCartRepository)
{
  // Set fields for use in some methods later...
  _customerRepository = customerRepository;
  _shoppingCartRepository = shoppingCartRepository;
}

然后,当您希望 ICheckoutService 实现执行一些工作时,您告诉 IoC 容器它应该为每种接口(interface)类型使用哪个具体类,并要求它为您构建一个 ICheckoutService。您的 IoC 容器将为您构建类,将正确的具体类注入(inject) CheckoutService 的构造函数。它还将在此处沿类层次结构一直构建依赖项,因此,例如,如果您的 ShoppingCartRepository 在构造函数中采用 IDatabaseSession 接口(interface),那么只要您告诉它要使用哪个具体类,您的 IoC 容器也会注入(inject)该依赖项为您的 IDatabaseService。

以下是您在配置时可能会用到的一些代码(例如)StructureMap作为您的 IoC 容器(此代码通常会在应用程序启动期间调用):

public class AppRegistry : Registry
{
  public AppRegistry()
  {
    ForRequestedType<ICheckoutService>().TheDefaultIsConcreteType<CheckoutService>();
    ForRequestedType<ICustomerRepository>().TheDefaultIsConcreteType<CustomerRepository>();
    // etc...
  }
}

然后为了获得 ICheckoutService 的实例并准备好运行,将所有依赖项传递给您的构造函数,您可以使用如下内容:

var checkoutService = ObjectFactory.GetInstance<ICheckoutService>();

我希望这是有道理的!

关于c# - 通过构造函数在 IoC 中强制执行依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/756541/

相关文章:

c# - IoC、依赖注入(inject)和构造函数参数

c# - 更改 Xml 声明,或选择没有声明部分的 xml

c# - 在扩展 Roles 表后,实体类型 IdentityRole 不是当前上下文模型的一部分

C#比较字符串中的字符

c# - 是否有一种流畅的 NHibernate 方法可以索引所有外键而无需编码?

typescript 警告 "Use an interface instead of a type literal"

c# - 如何使用反射获取接口(interface)的所有实现?

android - 使按钮更容易点击

c# - 在 Azure 应用程序中为两个存储帐户设置依赖项注入(inject)

java - 如何使用 @Value Spring 注解注入(inject) Map?