我可以在层次结构中使用DI容器来创建新对象吗?对于每个DI容器,您设置依赖项,然后按类型说出getInstance,它会正确创建实例。此外,您可以阅读许多文章,这些文章解释了DI容器应位于main函数的层次结构顶部,并且不应传递或单个传递。但是,如果我想从容器的层次结构中获取容器中的实例呢?
答案 0 :(得分:1)
避免让应用程序代码(启动代码除外)直接依赖容器或容器上的抽象;这是一种称为Service Locator的反模式。启动代码通常称为Composition Root。
组合根是应用程序中单独的层。该图层位于其他图层的顶部,例如表示层和业务层。
但这并不意味着在某些条件之后,您无法使用容器以惰性方式创建对象图的一部分。这是一个例子:
// Defined in a shared library of your application, accessible to all other
// code in your application.
public interface ICommandProcessor
{
public void Process(object command);
}
此接口的可能用法如下:
this.commandProcessor.Process(new ShipOrderCommand(orderId));
虽然抽象没有注意到有关使用可能容器的任何内容,但是这种抽象的实现仍然可以依赖于一个。但由于应用程序代码不应依赖于容器,因此应在Composition Root(应用程序的启动路径)中定义此实现。这允许应用程序不会忘记此类工具的存在,而容器仍可用于解析对象图。以下是一个示例实现:
public class CommandProcessor : ICommandProcessor
{
private readonly Container container;
public CommandProcessor(Container container) {
this.container = container;
}
public void Process(object command) {
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = this.container.GetInstance(handlerType);
handler.Handle((dynamic)command);
}
}
很长一段时间,您可以使用容器以延迟方式创建对象图,只要应用程序中使用Container的唯一图层是您的合成根。