此刻我只是试图绕过IoC,我也是那里的一部分。我在另一篇关于SO的文章中发现的一个例子是:
http://blog.vascooliveira.com/unity-tutorial-and-examples/
我不太了解的是:
ILogger myExampleInstance = myContainer.Resolve(loggerType);
我不确定loggerType是什么,因为它没有在任何地方提及它。
我可以看到IoC在这种情况下允许我们创建一种编写日志的方法。我们不是在代码中实例化特定类型的记录器,而是使用IoC来创建ILogger接口,然后我们对其进行编码。这意味着我假设我们并不特别关心使用什么类型的Logger。如果我们不在乎,我很想知道为什么我们需要传递一个loggerType,或者我们如何知道loggerType是由于关注点的分离。
我是理解它的一半,但我只需要最后的推动! =)
答案 0 :(得分:5)
你看到的实际上是一种叫做Service Locator的反模式。示例代码直接引用容器,调用其Resolve()方法。
在99%的情况下,您不应该在代码中引用容器 - 在代码的最高级别应该只有一个应用程序范围的容器引用。 (最后1%的案例几乎完全是您正在使用的框架不允许依赖注入的情况)
在对容器的单个引用中,根据需要新建对象,并将所有依赖项注入有效状态。所有对象都接收它们的依赖项作为参数(通常传递给构造函数)。
有很多博客文章(以下是我发现的一些快速谷歌搜索:Thou Shalt Not Reference The IoC Container和Service Locator Is An Anti Pattern,解释了ServiceLocator错误的各种原因。
您已经找到了一个关于loggerType应该是什么的问题的示例,使用适当的IoC,您的应用程序不应该关心 - 服务定位器方法往往意味着您的应用程序开始再次意识到其依赖关系的细节,这违背了首先使用IoC和dependecy注入的全部内容。
有关IoC的进一步阅读,我建议浏览StructureMap的创作者Jeremy Miller的博客文章。不要因为我说使用StructureMap而不是Unity,但是因为他从头开始写了一个容器,他对这个主题所说的大部分内容都经过深思熟虑,并且他是一位优秀的作家。
答案 1 :(得分:3)
就像这样
public class MyLogger : ILogger
{
//implementation
}
然后
Type loggerType = typeof(MyLogger);
ILogger myExampleInstance = myContainer.Resolve(loggerType);
output = myExampleInstance.MyInterfaceMethod("Unity rocks!");
问题是,它实际上是ServiceLocator模式。 DI和IoC看起来像这样:
public class Foo
{
private ILogger logger;
//This will be injected automatically by IoC
//once you register it somewhere in the app init e.g.
//container.RegisterType<ILogger, MyLogger>();
public Foo(ILogger logger)
{
this.logger = logger;
}
public void Bar()
{
logger.Debug("In the bar");
}
}
答案 2 :(得分:1)
虽然David Hall的答案更为正确,但只是为了回答您的问题,loggerType
是记录器的Type
。实际上,他们可能已经做到了:
ILogger myExampleInstance = myContainer.Resolve(typeof(ILogger));
甚至更好,使用通用扩展方法:
var myExampleInstance = myContainer.Resolve<ILogger>();
Unity容器将查看其已知映射列表,并查看从ILogger
映射的类型。然后它将创建一个新实例,并将其返回。
作为一个更简洁的例子:
IContainer container = ...;// get or create Unity container
container.RegisterType<ILogger, MyLogger>(); // tell Unity that when I ask for ILogger, I want a MyLogger back
ILogger logger = container.Resolve<ILogger>(); // logger is set to a new instance of MyLogger
我希望有所帮助!