关于微软Unity IoC的简短问题

本文关键字:IoC 问题 Unity 于微软 微软 | 更新日期: 2023-09-27 18:08:43

现在我正在努力理解IoC,我已经走到了这一步。我在另一篇关于SO的文章中发现了这样一个例子:

http://blog.vascooliveira.com/unity-tutorial-and-examples/

我不太明白的那句话是:

ILogger myExampleInstance = myContainer.Resolve(loggerType);

我不确定loggerType是什么,因为它没有提到它的任何地方。

我可以看到,在这种情况下,IoC允许我们创建一种写日志的方式。我们不是在代码中实例化特定类型的日志记录器,而是使用IoC创建一个日志记录器接口,并对其进行编码。这意味着我假设我们并不特别关心正在使用什么类型的Logger。如果我们不关心,我很想知道为什么我们需要传入一个loggerType,或者我们如何知道loggerType是什么,因为关注点分离。

我已经明白了一半,但我只需要最后一推!div =)

您看到的实际上是一个称为服务定位器的反模式。示例代码直接引用容器,调用它的Resolve()方法。

在99%的情况下,你不应该在你的代码中引用你的容器——在你的代码的最高层,应该只有一个应用程序范围内对容器的引用。(最后1%的情况几乎完全是你使用的框架不允许依赖注入)

在对容器的单一引用中,您可以根据需要新建对象,并以有效状态注入所有依赖项。所有的对象都以参数的形式接收它们的依赖项(通常是传递给构造函数)。

有很多博客文章(这里有两篇是我在谷歌上快速搜索到的:"你不应该引用IoC容器"answers"服务定位器是一个反模式")围绕着解释ServiceLocator不好的各种原因。

您已经找到了一个关于loggerType应该是什么的例子,使用适当的IoC您的应用程序不应该关心-服务定位器方法往往意味着您的应用程序开始再次意识到其依赖项的细节,这违背了首先使用IoC和依赖项注入的整个要点。

要进一步了解IoC,我建议浏览一下StructureMap的创建者Jeremy Miller的博客文章。不要以为我说要用StructureMap而不是Unity,但既然他从头开始写了一个容器,他所说的关于这个主题的大部分内容都是经过深思熟虑的,他是一个优秀的作家。

关于微软Unity IoC的简短问题

应该是这样的

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");
    }   
}

而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

我希望这对你有帮助!