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

使用 Unity 容器的依赖注入

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (15投票s)

2017 年 4 月 4 日

CPOL

5分钟阅读

viewsIcon

135432

文章《使用 Unity 容器进行依赖注入》首发于 codecompiled。依赖注入是实现控制反转的一种方式。要理解依赖注入,请参考“.NET 中的依赖注入”。依赖注入在运行时注入类的依赖项。这

文章《使用 Unity 容器进行依赖注入》首发于 codecompiled

依赖注入在运行时注入类的依赖项。这创建了松耦合
类之间的关系,因此一个类的更改不会影响其他依赖类。
DI 容器:为了自动注入依赖项,我们使用依赖注入(DI)容器。我们也可以手动注入依赖项,但使用 DI 容器具有以下优点:

自动依赖解析 当依赖项由容器管理时,出错的可能性更小。假设我们的应用程序有很多依赖项,那么在没有 DI 容器的情况下注入这些依赖项也很难管理。

解耦客户端与依赖项 如果客户端直接注入依赖项,则客户端代码将了解类的依赖项。这种紧耦合可能会成为问题,如果将来类的依赖项发生变化。

假设 X 依赖于 Y,那么在没有容器的情况下,客户端有责任创建并注入类 Y 的实例。

有一些流行的 .NET 依赖注入容器,例如:

  • Castle Windsor
  • StructureMap
  • Autofac
  • Unity
  • Ninject

在下面的示例中,我们将使用 Unity 来管理依赖项。它有一个简单的 API,并且易于配置。

我们有以下 Employee 类,它将 IDBAccess 作为构造函数依赖项。要使用依赖注入创建松耦合的架构,我们使用一个接口
这消除了类之间的直接依赖。因此,我们在 Employee 类的构造函数中使用 IDBAccess 参数。

class Employee
{
public string Name { get; set; }
IDBAccess _DBAccess;
public Employee(IDBAccess DBAccess)
{
_DBAccess=DBAccess;
}
}

将 Unity 添加到我们的应用程序中

要使用 Unity DI 容器实现依赖注入,我们添加 Unity 的 Nuget 包,该包将所需的引用添加到项目中。

Unity DI container

添加上述 Nuget 包会将以下引用添加到项目中:

Unity DI Container

项目中添加了以下引用:

Microsoft.Practices.UnityMicrosoft.Practices.Unity.RegistrationByConvention — 实现依赖注入功能的主要程序集。
Microsoft.Practices.Unity.Configuration 我们可以将依赖项注册在 xml 文件中,也可以在代码中注册。当我们在 xml 文件中注册依赖项时,此程序集很有用。

使用 Unity 容器

我们将对象注册到容器中,然后从容器中检索对象,所以客户端直接交互的是容器。

在我们的应用程序中使用 Unity DI 容器有两个主要步骤。

注册依赖项 我们使用 RegisterType 方法注册依赖项。它是一个泛型方法,我们在其中提供接口类型或抽象类与在客户端请求接口类型对象时需要实例化的具体类型之间的映射。首先,我们实例化容器。一旦我们有了容器对象,我们就使用 ResgisterType<Interface,ConcreteType>() 方法来添加接口和具体类型之间的映射。

var container = new UnityContainer();
container.RegisterType<IDBAccess, SQLDataAccess>();

上述依赖项在 IDBAccess 和 SQLDataAccess 类型之间添加了映射。这意味着,每当需要 IDBAccess 类型的依赖项时,就会创建一个 SQLDataAccess 实例并将其注入到依赖类型中。

解析依赖项 要创建通过构造函数或属性注入使用依赖项的对象,我们使用 resolve 方法。当我们使用 resolve 方法时,必要的依赖项会自动注入。因此,我们无需关心自己提供依赖项。我们可以使用 Resolve() 方法获取 Employee 类的对象,如下所示:

Employee employee = container.Resolve<Employee>();

上面对 Resolve() 方法的调用将自动将所需的依赖项注入 Employee 类。由于 Employee 类依赖于 IDBAccess 接口,并且我们已经注册了 IDBAccess 接口和 SQLDataAccess 类之间的映射,因此容器会自动创建 SQLDataAccess 对象并将其传递给 Employee 类的构造函数。

namespace DIContainer
{
class Employee
{
public string Name { get; set; }
IDBAccess _DBAccess;
public Employee(IDBAccess DBAccess)
{
_DBAccess=DBAccess;
}
}


interface IDBAccess
{
string connection { get; set; }
}

class SQLDataAccess:IDBAccess
{

public string _connection;
public string connection
{
get
{
return "test connection";
}
set
{
_connection=value;
}
}
}


class Program
{
static void Main(string[] args)
 {
var container = new UnityContainer();
container.RegisterType<IDBAccess, SQLDataAccess>();
Employee emp = container.Resolve<Employee>();
 }
}
}

属性注入

要实现属性注入,我们需要将 [Dependency] 属性应用于类中的属性。
假设我们有一个 employee 类,它公开了一个 PersonalDetails 属性,那么我们可以这样使用属性注入:

public class Employee
{
private personalDetails

[Dependency]
public PersonalDetails PersonalDetails
{
get { return personalDetails; }
set { supplier = personalDetails; }
}
}

现在,当我们使用 Unity 容器创建 Employee 对象时,PersonalDetails 对象会自动创建并赋值给 PersonalDetails 属性。

将所有类型注册放在一起很重要。如果我们把类型注册放在一起,那么我们就可以在代码中从一个位置管理注册。我们在应用程序启动时将注册添加到 Unity 容器,以便稍后在应用程序生命周期中可以使用这些类型。对于 Web 应用程序,这意味着在 global.asax 中将类型注册到容器中;而对于控制台应用程序,我们可以在 Main() 方法中注册依赖项。

在配置文件中注册依赖项

虽然在代码中将类型注册到容器是更好的方法,因为它允许轻松捕获错误。但这也意味着需要重新编译代码。在 Unity 容器中注册类型的另一种方法是使用配置文件。如果使用配置文件,我们可以轻松地更改注册而无需重新编译代码。

以下是一个示例 XML 配置文件,它在 Unity 容器中注册依赖项。我们注册的类型与上面在代码中注册的类型相同。

<?xml version="1.0" encoding="utf-8"?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<configSections>
 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
 </configSections>
<typeAliases>
<typeAlias alias="IDBAccess" type="DIContainer.IBook,DIContainer" />
<typeAlias alias="SQLDataAccess" type="DIContainer.IBook,DIContainer" />
</typeAliases>
<container>
<register type="IDBAccess" mapTo="SQLDataAccess" />
</container>
</unity>

我们可以这样配置 Unity 容器:

var container = new UnityContainer();
var section =(UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);

通过实现 Unity 容器的依赖注入,我们可以在应用程序启动时轻松地在 Unity 容器中注册应用程序的依赖项。我们可以要求 Unity 容器为我们创建对象,它将自动解析依赖项。当我们在一个应用程序中很难自己管理类型之间的依赖项时,这一点会更有用。

文章《使用 Unity 容器进行依赖注入》首发于 codecompiled

© . All rights reserved.