Jef*_*ght 9 c# abstract-class dependency-injection interface inversion-of-control
我正在尝试使用IoC /依赖注入,同时编程为契约而不是特定的类.我所面临的困境是两者之间的紧张关系:
为IoC接口编程:我开始时IoC严重依赖接口.从Spring的示例项目来看,接口是在编写与IoC签订合同时的方法.
(...虽然抽象类通常是首选的:接口的主要缺点是,当允许API的演变时,它们的灵活性远远低于类)
通过构造函数使类依赖性显式化 我的直觉是,将依赖项传递给类的构造函数是一种很好的编程习惯.实际上,这是依赖注入.
...除非您不能在接口/抽象语句中强制执行构造函数签名:接口或抽象类都不允许定义构造函数签名(轻松/优雅).另请参见框架设计指南第4.4节: 不要在抽象类型中定义公共或受保护的内部构造函数....只有当用户需要创建该类型的实例时,构造函数才应该是公共的.
这个问题与之前的stackoverflow问题有关:定义构造函数签名的接口?
但我的问题是:
因为您无法在C#接口/抽象类中定义构造函数,正如上面的问题所要求的那样,在实际层面上:
你如何将这与通过构造函数传递依赖关系的明智做法相协调?
编辑:谢谢你的回答.我希望能在这种情况下对我应该做些什么有所了解.只是不使用contructor args?使用某种确实采用依赖关系的Init()方法?编辑2:谢谢你的答案,非常有帮助.
我一直认为用(制作)的例子更容易解释...
想象一下,你有一个ICustomerRepository接口,一个IShoppingCartRepository接口和一个ICheckout接口.您具有这些接口的具体实现 - CustomerRepository,ShoppingCartRepository和CheckoutService.
您的CheckoutService具体类有一个构造函数,它接受一个ICustomerRepository和一个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)
我希望这是有道理的!