目录
介绍
总览
依赖注册
实例注册
工厂注册
类型注册
样例应用程序
总结
介绍这是我关于依赖反转原理和依赖注入的文章的第五部分也是最后一部分。在上一部分中,我实现了一个自定义容器,其功能非常有限,可用于注册依赖项并在需要依赖项实例时进行解析。现在,有很多工具可以用来实现依赖注入,例如UnityContainer,StructureMap,Windsor Castle,NInject等等。在这一部分中,我将解释所提供的不同功能UnitContainer以及如何注册依赖项以及如何解决已注册的依赖项。
如果您是该部分的直接访问者,可能会很难理解代码。因此,在开始阅读本文之前,请仔细阅读前面的部分。为了方便地浏览以前的文章,我提供了以下链接:
- 第1部分:依赖倒置原则
- 第2部分:控制反转和IoC容器
- 第3部分:自定义IoC容器
- 第4部分:具有生命周期选项的自定义IoC容器
- 第5部分:使用Microsoft Unity的依赖注入(DI)(当前正在阅读)
Unity容器(Unity)是功能齐全的可扩展依赖项注入容器。它有助于构建松耦合应用程序,并为开发人员提供以下优势:
- 简化的对象创建,尤其是对于分层对象结构和依赖项
- 需求抽象;这使开发人员可以在运行时或配置中指定依赖项,并简化横切关注点的管理
- 通过将组件配置推迟到容器来提高灵活性
- 服务定位能力;这允许客户端存储或缓存容器
- 实例和类型拦截
- 约定注册
通过[https://github.com/unitycontainer/unity]
依赖注册注册一个依赖项可使IoC容器知道依赖项的具体实现。例如,如果要在请求解析IReader依赖项时获取KeyboardReader实例,则需要注册IReader解析KeyboardReader类实例的依赖项。以下是使用Unity容器进行依赖项注册的示例。
IUnityContainer container = new UnityContainer();
container.RegisterType();
通过上述注册,解析类型IReader[container.Resolve()]时,将返回一个KeyboardReader实例。
UnityContainer通过以下方式支持依赖项注册。
实例注册通过执行实例注册,我们告诉IoC容器,当有人请求解决依赖性时,将返回注册的实例。在要以特定状态注册依赖项的情况下,实例注册非常有用。该RegisterInstance()方法用于在容器中注册实例。
var keyboardReader = new KeyboardReader();
container.RegisterInstance(keyboardReader);
通过上述注册,解析类型KeyboardReader[ container.Resolve()]时,将返回注册的实例。
实例可以使用名称在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。
实例注册还支持类型映射。这意味着可以针对类型(类或接口)注册实例,以便在解析该类型时,已注册的实例将返回给调用方。示例如下:
var keyboardReader = new KeyboardReader();
container.RegisterInstance(keyboardReader);
通过上述注册,解析类型KeyboardReader[ container.Resolve()]时,将返回注册的keyboardReader实例。
使用工厂注册,我们可以基于函数调用的输出来注册依赖项。在注册实例时,它提供了更多控制权。
var keyboardReader = new KeyboardReader();
container.RegisterFactory(fn => new KeyboardReader());
类型注册
类型注册是广泛使用的注册。在这种类型的注册中,我们需要提供锲约类型和具体类型,其中解析锲约类型将产生具体类型的实例。类型注册的最低要求是类型本身。以下是注册示例:
container.RegisterType();
通过上述注册,解析类型KeyboardReader[ container.Resolve()]时,将返回KeyboardReader的实例。
以下是注册的另一个示例,我们可以提供锲约类型及其具体类型。
container.RegisterType(); // default registration
通过上述注册,解析类型KeyboardReader[ container.Resolve()]时,将返回KeyboardReader的实例。
我们还可以在注册类型时提供名称:
container.RegisterType("Keyboard");
通过上面的注册来解决依赖关系,我们需要使用container.Resolve("Keyboard")。
注意:名称的默认值为null。当我们注册一个类型而不传递任何名称时,这种注册称为default registration。
样例应用程序让我们使用Visual Studio创建一个控制台应用程序。在此演示应用程序中,我使用了Visual Studio 2019。但是您可以使用任何版本的Visual Studio(Visual Studio 2012及更高版本)。
右键单击该项目,然后单击“管理NuGet软件包... ”。管理NuGet包用于将3个第三方库添加的应用程序。
在“管理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();
var reader = container.Resolve();
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键运行控制台应用程序。
您将获得以下输出:
如您所见,我们已经使用Typed注册为KeyboardReader具体类型注册了IReader类型。因此,当我们尝试解析类型IReader时,我们将获得KeyboardReader的实例。并调用Read()方法将返回“Reading from keyboard ... ”,该信息已打印在控制台上。
总结在本文的这一部分中,我解释了什么是UnityContainer,如何注册依赖关系,并创建了一个演示应用程序以显示使用UnityContainer注册和解决依赖关系。