通过构造函数在IoC中实现依赖关系?

Jef*_*ght 9 c# abstract-class dependency-injection interface inversion-of-control

我正在尝试使用IoC /依赖注入,同时编程为契约而不是特定的类.我所面临的困境是两者之间的紧张关系:

  1. 为IoC接口编程:我开始时IoC严重依赖接口.从Spring的示例项目来看,接口是在编写与IoC签订合同时的方法.

  2. (...虽然抽象类通常是首选的:接口的主要缺点是,当允许API的演变时,它们的灵活性远远低于类)

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

  4. ...除非您不能在接口/抽象语句中强制执行构造函数签名:接口或抽象类都不允许定义构造函数签名(轻松/优雅).另请参见框架设计指南第4.4节: 不要在抽象类型中定义公共或受保护的内部构造函数....只有当用户需要创建该类型的实例时,构造函数才应该是公共的.

这个问题与之前的stackoverflow问题有关:定义构造函数签名的接口?

但我的问题是:

因为您无法在C#接口/抽象类中定义构造函数,正如上面的问题所要求的那样,在实际层面上:

你如何将这与通过构造函数传递依赖关系的明智做法相协调

编辑:谢谢你的回答.我希望能在这种情况下对我应该做些什么有所了解.只是不使用contructor args?使用某种确实采用依赖关系的Init()方法?编辑2:谢谢你的答案,非常有帮助.

Ste*_*ock 8

我一直认为用(制作)的例子更容易解释...

想象一下,你有一个ICustomerRepository接口,一个IShoppingCartRepository接口和一个ICheckout接口.您具有这些接口的具体实现 - CustomerRepository,ShoppingCartRepository和CheckoutService.

您的CheckoutService具体类有一个构造函数,它接受一个I​​CustomerRepository和一个IShoppingCartRepository - 例如

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

然后,当您希望ICheckoutService实现执行某些操作时,您可以告诉IoC容器它应该为每种接口类型使用哪个具体类,并要求它为您构建ICheckoutService.您的IoC容器将为您构建您的类,将正确的具体类注入CheckoutService的构造函数中.它也会在这里继续在类heirarchy中构建依赖关系,所以如果你的ShoppingCartRepository在构造函数中使用了一个IDatabaseSession接口,那么你的IoC容器也会注入该依赖关系,只要你告诉它使用哪个具体的类.为您的IDatabaseService.

下面是配置(例如)StructureMap作为IoC容器时可能使用的一些代码(通常在app启动期间调用此代码):

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

然后,为了获得一个ICheckoutService的实例,并准备好了,将所有依赖项传递给构造函数,你可以使用类似的东西:

var checkoutService = ObjectFactory.GetInstance<ICheckoutService>();
Run Code Online (Sandbox Code Playgroud)

我希望这是有道理的!