65.9K
CodeProject 正在变化。 阅读更多。
Home

依赖倒置原则、IoC容器和依赖注入:第五部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (7投票s)

2020 年 4 月 23 日

CPOL

5分钟阅读

viewsIcon

8703

什么是UnityContainer以及注册依赖的不同方式

引言

这是我关于依赖倒置原则和依赖注入的文章的第五部分,也是最后一部分。在上一部分中,我实现了一个功能非常有限的自定义容器,可以用于注册依赖并在需要依赖实例时解析。现在有很多工具可以实现依赖注入,例如UnityContainerStructureMapWindsor CastleNInject等等。在这一部分,我将解释UnitContainer提供的不同功能,以及如何注册依赖和解析已注册的依赖。

如果您是直接访问本部分的读者,可能会发现代码难以理解。因此,在开始阅读本文之前,请先浏览前面的部分。为了方便导航到之前的文章,我在下面提供了链接:

概述

Unity Container (Unity) 是一个功能齐全、可扩展的依赖注入容器。它有助于构建松耦合的应用程序,并为开发人员提供以下优势:

  • 简化的对象创建,特别是对于分层对象结构和依赖项。
  • 抽象化需求;这允许开发人员在运行时或配置文件中指定依赖项,并简化横切关注点的管理。
  • 通过将组件配置推迟到容器来增加灵活性。
  • 服务定位功能;这允许客户端存储或缓存容器。
  • 实例和类型拦截。
  • 按约定注册。

来自[https://github.com/unitycontainer/unity]

依赖注册

注册依赖项可以让IoC容器知道依赖项的具体实现。例如,如果我们想在请求解析IReader依赖项时获取KeyboardReader的实例,我们就需要注册一个解析KeyboardReader类实例的IReader依赖项。以下是使用Unity容器注册依赖项的示例。

IUnityContainer container = new UnityContainer();

container.RegisterType<IReader, KeyboardReader>();

通过上述注册,在解析类型IReader [container.Resolve<IReader>()]时,将返回KeyboardReader的一个实例。

UnityContainer支持以下几种依赖注册方式:

实例注册

通过实例注册,我们告诉IoC容器,当有人请求解析依赖项时,将返回已注册的实例。当您想以特定状态注册依赖项时,实例注册非常有用。RegisterInstance()方法用于在容器中注册实例。

var keyboardReader = new KeyboardReader();

container.RegisterInstance(keyboardReader);

通过上述注册,在解析类型KeyboardReader [container.Resolve<KeyboardReader>()]时,将返回已注册的实例。

实例可以与名称一起注册到IoC容器中。示例如下:

var keyboardReaderA = new KeyboardReader();
var keyboardReaderB = new KeyboardReader();

container.RegisterInstance("InstanceA", keyboardReaderA);
container.RegisterInstance("InstanceB", keyboardReaderB);

通过上述注册,在解析类型KeyboardReader时,我们需要提供名称,因为不存在没有名称的注册。因此,在上述情况下,通过container.Resolve(KeyboardReader, "InstanceA")解析类型KeyboardReader将返回keyboarderReaderA实例,而通过container.Resolve(KeyboardReader, "InstanceB")解析类型KeyboardReader将返回keyboardReaderB

实例注册也支持类型映射。这意味着一个实例可以 against 一个类型(类或接口)注册,以便在解析该类型时,将已注册的实例返回给调用者。示例如下:

var keyboardReader = new KeyboardReader();

container.RegisterInstance<IReader>(keyboardReader);

通过上述注册,在解析类型KeyboardReader [container.Resolve<IReader>()]时,将返回已注册的keyboardReader实例。

工厂注册

通过工厂注册,我们可以基于函数调用的输出注册依赖项。这在注册实例时提供了更多的控制。

var keyboardReader = new KeyboardReader();

container.RegisterFactory<IReader>(fn => new KeyboardReader());

类型注册

类型注册是最常用的注册方式。在这种类型的注册中,我们需要提供契约类型和具体类型,其中解析契约类型将产生具体类型的实例。类型注册的最低要求是类型本身。以下是注册的示例:

container.RegisterType<KeyboardReader>();

通过上述注册,在解析类型KeyboardReader [container.Resolve<KeyboardReader>()]时,将返回KeyboardReader的一个实例。

以下是另一个注册示例,其中我们可以提供契约类型及其具体类型。

container.RegisterType<IReader, KeyboardReader>(); // default registration

通过上述注册,在解析类型KeyboardReader [container.Resolve<IReader>()]时,将返回KeyboardReader的一个实例。

我们也可以在注册类型时提供名称。

container.RegisterType<IReader, KeyboardReader>("Keyboard");

通过上述注册,要解析依赖项,我们需要使用container.Resolve<IReader>("Keyboard")

注意:名称的默认值为null。当我们注册一个类型而不传递任何名称时,这种注册称为默认注册

示例应用

让我们使用Visual Studio创建一个控制台应用程序。在这个演示应用程序中,我使用了Visual Studio 2019。但是您可以使用任何版本的Visual Studio(从Visual Studio 2012开始)。

右键单击项目,然后单击“管理NuGet程序包…”。管理NuGet程序包用于将第三方库添加到应用程序中。

在“管理NuGet程序包”窗口中,选择浏览选项,搜索Unity并安装该程序包。在撰写本文时,Unity的最新版本是5.11.6。但是您可以使用任何稳定版本用于演示应用程序。

Program.cs文件中添加以下代码行:

using System;
using Unity;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IUnityContainer container = new UnityContainer();
            container.RegisterType<IReader, KeyboardRader>();
            var reader = container.Resolve<IReader>();
            var readText = reader.Read();
            Console.WriteLine($"The output is : {readText}");
            Console.ReadLine();
        }
    }
    
    interface IReader
    {
        string Read();
    }

    class KeyboardRader : IReader
    {
        public string Read()
        {
            return "Reading from keyboard...";
        }
    }
}

您的示例应用程序已准备好运行。按F5运行控制台应用程序。

您将获得以下输出:

正如您所注意到的,我们已经通过类型注册将IReader类型注册为KeyboardReader具体类型。因此,当我们尝试解析IReader类型时,我们将获得KeyboardReader的实例。调用Read()方法将返回“Reading from keyboard...”,并显示在控制台上。

UnityContainer提供了更多功能,我将在下一篇文章中介绍。此外,我将向您展示注入依赖项的不同方法。

摘要

在本篇文章中,我解释了UnityContainer是什么,如何注册依赖项,并创建了一个演示应用程序来展示使用UnityContainer注册和解析依赖项。

历史

  • 2020 年 4 月 23 日:初始版本
© . All rights reserved.