Tutorialsteacher

关注我们

文章
  • C#
  • C# 面向对象编程
  • ASP.NET Core
  • ASP.NET MVC
  • LINQ
  • 控制反转 (IoC)
  • Web API
  • JavaScript
  • TypeScript
  • jQuery
  • Angular 11
  • Node.js
  • D3.js
  • Sass
  • Python
  • Go lang
  • HTTPS (SSL)
  • 正则表达式
  • SQL
  • SQL Server
  • PostgreSQL
  • MongoDB
  • IoC - 入门
  • 介绍
  • 控制反转
  • DIP
  • 依赖注入
  • IoC 容器
  • Unity 容器
  • 安装 Unity 容器
  • 注册和解析
  • 构造函数注入
  • 属性注入
  • 方法注入
  • 覆盖
  • 生命周期管理器
Entity Framework Extensions - 提升 EF Core 9
  批量插入
  批量删除
  批量更新
  批量合并

Unity 容器:注册和解析

在上一节中,我们在控制台项目中安装了 Unity 框架。在这里,我们将学习如何使用 Unity 容器注册类型映射并解析它。

正如我们在 IoC 容器章节中学到的,每个容器都必须提供注册和解析依赖项的方法。Unity 容器为此提供了 RegisterType() 和 Resolve() 方法。

我们将在本章中使用以下示例类来演示依赖项的注册和解析。

示例:C#
public interface ICar
{
    int Run();
}

public class BMW : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Ford : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Audi : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }

}
public class Driver
{
    private ICar _car = null;

    public Driver(ICar car)
    {
        _car = car;
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} - {1} mile ", _car.GetType().Name, _car.Run());
    }
}

正如你在示例类中看到的,Driver 类依赖于 ICar 接口。因此,当我们实例化 Driver 类对象时,我们将不得不传入一个实现 ICar 接口的类的实例,例如 BMW、Audi 或 Ford 类,如下所示。

示例:C#
Driver driver = new Driver(new BMW());

driver.RunCar();
输出
行驶中的宝马 - 1 英里

在上面的示例中,我们在创建 Driver 类对象时创建并传入了一个 BMW 对象。因此,我们手动注入了 Driver 类的依赖项。现在,我们将使用 Unity 容器来了解注册和解析依赖项的不同方式。

使用 UnityContainer

为了使用 Unity 容器,我们首先需要创建它的一个对象。你可以使用任何实现 IUnityContainer 接口的类。Unity 容器在 Microsoft.Practices.Unity 命名空间中包含了实现 IUnityContainer 接口的 UnityContainer 类。如果你需要扩展容器,那么你可以创建自己的自定义类并根据需要实现 IUnityContainer 接口。

示例:实例化 UnityContainer - C#
using Microsoft.Practices.Unity;

IUnityContainer container = new UnityContainer();
//or
var container = new UnityContainer();

接下来,我们需要注册类型映射。

注册

在 Unity 解析依赖项之前,我们需要向容器注册类型映射,以便它能为给定类型创建正确的对象。使用 RegisterType() 方法注册类型映射。基本上,它配置了为哪个接口或基类实例化哪个类。例如,如果我们希望 Unity 容器在需要提供 ICar 接口的依赖项时创建并提供一个 BMW 类的对象,那么我们首先需要按照如下所示注册它。

示例:使用 Unity 注册类型 - C#
IUnityContainer container = new UnityContainer();

container.RegisterType<ICar, BMW>();

这里,container.RegisterType<ICar, BMW>() 请求 Unity 在需要注入 ICar 对象时,创建一个 BMW 类的对象并通过构造函数注入它。

RegisterType 方法包含许多重载。在 MSDN 上了解 RegisterType 的所有重载。

所以现在,注册之后,我们可以使用 Resolve() 方法。

解析

Unity 使用 resolve() 方法创建指定类的对象并自动注入依赖项。我们上面将 BMW 注册到 ICar。现在,我们可以使用 Unity 容器实例化 Driver 类,而无需使用 new 关键字,如下所示。

示例:解析 - C#
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();// Map ICar with BMW 

//Resolves dependencies and returns the Driver object 
Driver drv = container.Resolve<Driver>(); 
drv.RunCar();
输出
行驶中的宝马 - 1 英里

在上面的示例中,Unity 容器使用 container.Resolve<Driver>() 方法创建了 Driver 类的一个对象。Driver 类是 ICar 的依赖项。因此,container.Resolve<Driver>() 通过自动创建并注入一个 BMW 对象来返回 Driver 类的一个对象。所有这些都在幕后进行。BMW 对象被创建并注入,因为我们将 BMW 类型注册到了 ICar。

每次我们解析相同的类型时,Unity 容器都会创建一个新对象并注入它。

var container = new UnityContainer();
container.RegisterType<ICar, BMW>();

Driver driver1 = container.Resolve<Driver>();
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>();
driver2.RunCar();
输出
行驶中的宝马 - 1 英里
行驶中的宝马 - 1 英里

在上面的示例中,每当容器解析 Driver 类时,它都会注入 BMW 对象,例如 driver1 和 driver2 都引用了单独的 BMW 对象。

因此,你可以使用 Unity 容器创建指定类型的对象。在 MSDN 上了解 Resolve 方法的所有重载。

多次注册

如果你注册了相同类型的多个映射,Unity 容器将注入最后注册的类型。

IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>();

Driver driver = container.Resolve<Driver>();
driver.RunCar();
输出
奥迪行驶中 - 1 英里

在上面的示例中,ICar 映射到 BMW 和 Audi。然而,Unity 将每次注入 Audi,因为它最后注册。

注册命名类型

你可以注册一个带有名称的类型映射,然后你可以在 Resolve() 方法中使用该名称。

示例:注册命名类型 - C#
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");

ICar bmw = container.Resolve<ICar>();  // returns the BMW object
ICar audi = container.Resolve<ICar>("LuxuryCar"); // returns the Audi object

如上所示,我们已经将 ICar 映射到 BMW 和 Audi 类。然而,我们为 ICar-Audi 映射指定了名称 "LuxuryCar"。所以现在,如果我们指定映射名称,Resolve() 方法将返回一个 Audi 对象。

考虑以下示例

var container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");

// Registers Driver type            
container.RegisterType<Driver>("LuxuryCarDriver", 
                new InjectionConstructor(container.Resolve<ICar>("LuxuryCar")));

Driver driver1 = container.Resolve<Driver>();// injects BMW
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>("LuxuryCarDriver");// injects Audi
driver2.RunCar();
输出
行驶中的宝马 - 1 英里
奥迪行驶中 - 1 英里

在上面的例子中,我们用名称 "LuxuryCarDriver" 注册了 Driver 类,并指定了一个 InjectionConstructor 对象。new InjectionConstructor(container.Resolve<ICar>("LuxuryCar")) 为 Driver 类指定了一个构造函数注入,它传递了一个 Audi 对象,因为 container.Resolve<ICar>("LuxuryCar") 返回一个 Audi 对象。所以现在,我们可以使用 container.Resolve<Driver>("LuxuryCarDriver") 来解析带有 Audi 的 Driver,即使 ICar 默认注册为 BMW。

注册实例

Unity 容器允许我们使用 RegisterInstance() 方法注册现有实例。它不会为注册类型创建新实例,我们每次都将使用相同的实例。

var container = new UnityContainer();
ICar audi = new Audi();
container.RegisterInstance<ICar>(audi);

Driver driver1 = container.Resolve<Driver>();
driver1.RunCar();
driver1.RunCar();

Driver driver2 = container.Resolve<Driver>();
driver2.RunCar();
输出
奥迪行驶中 - 1 英里
奥迪行驶中 - 2 英里
奥迪行驶中 - 3 英里

因此,我们可以使用 Unity 容器注册和解析不同类型。在下一章中了解 Unity 容器如何执行构造函数注入。

TUTORIALSTEACHER.COM

TutorialsTeacher.com 是您权威的技术教程来源,旨在通过循序渐进的方法,指导您掌握各种网络和其他技术。

我们的内容旨在帮助所有水平的学习者轻松快速地学习技术。访问此平台即表示您已审阅并同意遵守我们的使用条款和隐私政策,这些条款旨在保护您的体验和隐私权。

[email protected]

关于我们使用条款隐私政策
copywrite-symbol

2024 TutorialsTeacher.com. (v 1.2) 版权所有。