假设我有一些类Foo,它有两个依赖项:ISerializer<T>
和IFileAccessHandler
。
现在这个类还有其他依赖项,功能依赖项。我不希望任何人在无效状态下实例化这个类,所以我还需要在构造函数中传递一个域对象。
但是当我实际创建类Foo的那一刻我还知道要传递哪个域对象时,如何处理IoC?
我使域对象成为我由Factory设置的属性。因此,Factory会调用Service Locator来获取一个正确实例化的“Foo”类及其依赖项,并使用正确的域对象进一步填充它并返回它。
但这是最好的方式吗?我本来希望让我的构造函数的域对象部分能够使它真实地需要使用“Foo”。
有什么想法吗? 我在这里错过了什么吗?
答案 0 :(得分:70)
如果在注册时无法连接具体类型,DI的默认解决方案是使用抽象工厂
在您的情况下,我将定义一个IFooFactory接口:
public interface IFooFactory
{
Foo Create(DomainClass dc);
}
这将允许您定义了解基础结构服务的具体实现。
public class FooFactory : IFooFactory
{
private readonly ISerializer serializer;
private readonly IFileAccessHandler fileHandler;
public FooFactory(ISerializer serializer, IFileAccessHandler fileHandler)
{
if(serializer == null)
{
throw new ArgumentNullException("serializer");
}
if(fileHandler == null)
{
throw new ArgumentNullException("fileHandler");
}
this.serializer = serializer;
this.fileHandler = fileHandler;
}
public Foo Create(DomainClass dc)
{
return new Foo(this.serializer, this.fileHandler, dc);
}
}
通过这种方式,您可以保护您的Foo类的不变量,使您能够继续使用构造函数注入。
在DI容器中,您可以注册IFooFactory和相应的实现。你有一个DomainClass实例并需要一个Foo实例,你就会依赖IFooFactory并使用它。
答案 1 :(得分:0)
我也在努力解决这个问题。 Mark的例子受到限制,因为FooFactory正在创建一个具体的类Foo。如果要创建一个在启动配置期间确定实现的IFoo,该怎么办?这意味着对于IFoo(FooA,FooB等)的每个替代实现,您将需要相应工厂的具体实现(FooAFactory,FooBFactory等)。这让我觉得多余。
如果工厂的定义与Container的实现和初始化相同,我没有看到工厂引用容器的弱点。它仍然使容器的引用不会泄漏到应用程序的其余部分。
致以最诚挚的问候,
地铁。