关于Microsoft Unity IoC的简单问题

发布于 2024-12-04 20:39:17 字数 574 浏览 1 评论 0原文

目前我只是想了解一下 IoC,我也是其中的一部分。我在 SO 的另一篇文章中找到的一个例子是:

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

我不太明白的是:

ILogger myExampleInstance = myContainer.Resolve(loggerType);

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

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

我只理解了一半,但我只需要最后的推动! =)

Just trying to wrap my head around IoC at the moment, and I am part of the way there. An example I found on another post on SO was this:

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

The line I don't quite get is this:

ILogger myExampleInstance = myContainer.Resolve(loggerType);

I am not sure what loggerType is as it doesn't mention it anywhere.

I can see that IoC in this case allows us to create a way of writing a log. Rather than instantiate in the code a specific type of logger, we use IoC to create an ILogger interface, and we code to that. This means I assume that we don't care specifically what type of Logger is being used. If we don't care, I am curious to know why we need to pass in a loggerType, or how we know what the loggerType is due to seperation of concerns.

I am half way to understanding it but I just need a final push! =)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

罪#恶を代价 2024-12-11 20:39:17

您看到的实际上是一个名为 Service Locator 的反模式。示例代码直接引用容器,调用其 Resolve() 方法。

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

在对容器的单个引用中,您可以根据需要新建对象,并将其所有依赖项注入到有效状态。所有对象都接收其依赖项作为参数(通常传递给构造函数)。

有很多博客文章(这里有两个我通过快速谷歌搜索找到的: 你不应该引用 IoC 容器

href="http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx" rel="nofollow">服务定位器是一种反模式,解释了ServiceLocator 已经找到一个例子来说明您关于 loggerType 应该是什么的问题,使用正确的 IoC 您的应用程序不应该关心 - 服务定位器方法往往意味着您的应用程序开始意识到其 loggerType 的详细信息再次依赖,这违背了使用 IoC 和依赖注入的初衷。

要进一步阅读 IoC,我建议浏览 StructureMap。不要以为我说的是使用 StructureMap 而不是 Unity,但由于他从头开始编写了一个容器,所以他在这个主题上所说的大部分内容都很好经过深思熟虑,他是一个好作家。

What you see there is actually an anti-pattern called Service Locator. The example code directly references the container, calling its Resolve() method.

In 99% of cases you should not ever reference your container within your code - there should only be a single application wide reference to the container at the very highest level of your code. (the final 1% of cases are almost exclusively where a framework you are using doesn't allow dependency injection)

In that single reference to your container you new up objects as needed with all their dependencies injected in a valid state. All your objects receive their dependencies as parameters (most often passing to the constructor).

There are lots of blog posts (here are two I found with some quick googling: Thou Shalt Not Reference The IoC Container and Service Locator Is An Anti Pattern around explaining the various reasons why ServiceLocator is bad.

You have found one example with your question about what loggerType should be, using proper IoC your application should not care - the Service Locator approach tends to mean your application starts to become aware of the details of its dependencies again, which goes against the entire point of using IoC and dependecy injection in the first place.

For further reading on IoC I'd suggest browsing through blog posts by Jeremy Miller, the creater of StructureMap. Don't take that as me saying use StructureMap instead of Unity, but since he wrote a container from scratch most of what he says on the subject is well thought out and he is a good writer.

游魂 2024-12-11 20:39:17

它会是这样的

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

It would be something like this

public class MyLogger : ILogger
{
    //implementation
}

And then

Type loggerType = typeof(MyLogger);

ILogger myExampleInstance = myContainer.Resolve(loggerType);
output = myExampleInstance.MyInterfaceMethod("Unity rocks!");

The problem is, it is actually a ServiceLocator pattern. The DI and IoC would look like this:

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");
    }   
}
乄_柒ぐ汐 2024-12-11 20:39:17

虽然 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

我希望有帮助!

While David Hall's answer is more correct, just to answer your question, loggerType is the Type of the logger. In reality, they probably could have done:

ILogger myExampleInstance = myContainer.Resolve(typeof(ILogger));

Or even better, use the generic extension method:

var myExampleInstance = myContainer.Resolve<ILogger>();

The Unity container will look into its list of known mappings, and see what type is mapped from ILogger. It will then create a new instance, and return it.

As a more concise example:

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

I hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文