.NET 的 IoC 容器 - Unity、Ninject、Autofac 一览






3.29/5 (19投票s)
本文主要比较了 .NET 中三个最流行的 DI 框架。
引言
DI(依赖注入)或 IoC(控制反转)主要用于管理应用程序中的依赖。DI 和 IOC 这两个术语代表相同的概念,它们基本上用于创建依赖并在需要时进行注入。这对于将紧耦合的组件变为松耦合的组件非常有帮助。市面上有许多 IoC 容器,但 Unity、Ninject 和 Autofac 是 .NET 中最常用和最流行的三个容器。
每个 DI 都有其优缺点。在本文中,我将通过一个示例演示这三个依赖注入在 .NET 中的实现。它将真正帮助您了解在应用程序开发过程中选择哪个最佳。
Unity
Unity IoC 容器由微软发布。它有助于构建松耦合的应用程序,并为开发人员提供以下优势:
- 简化的对象创建
- 需求抽象
- 一致的 API
- 良好的文档
它在使用任何应用程序时也非常有用,因为它具有可插拔的特性,因此在应用程序开发过程中无需更改配置。因此,我在这里为您提供一个小型 POC(概念验证),它基本上是一个控制台项目。首先,从 NuGet 包管理器下载 Unity 包。
成功安装包后,您将在项目中看到三个与 Unity 相关的引用。
在此实现中,我们主要创建了一个 `student` 类和一个 `University` 类。`Student` 类的显示结果基本上内部使用了 `University` 类,或者可以说它依赖于 `University` 类。因此,我们将通过 Unity 创建依赖。有三种方法可以注入依赖:构造函数注入、属性注入和方法注入。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using Microsoft.Practices.Unity;
namespace ExamManagementByUnity
{
public interface IStudent
{
}
public class Student : IStudent
{
private IUniversity _University;
[Dependency]
public IUniversity University
{
get { return _University; }
set { _University = value; }
}
//// Dependency Injection by constructor
//[InjectionConstructor]
//public Student(IUniversity tmpUniversity)
//{
// _University = tmpUniversity;
//}
//// Dependency Injection by method
//[InjectionMethod]
//public void SetObject(IUniversity tmpUniversity)
//{
// _University = tmpUniversity;
//}
public void DisplayResult()
{
_University.ShowResult();
}
}
public interface IUniversity
{
void ShowResult();
}
class University : IUniversity
{
public void ShowResult()
{
Console.WriteLine("You got first division in Engineering program.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;
namespace ExamManagementByUnity
{
class Program
{
static void Main(string[] args)
{
IUnityContainer unitycontainer = new UnityContainer();
unitycontainer.RegisterType<IUniversity, University>();
Student stu = unitycontainer.Resolve<Student>();
stu.DisplayResult();
Console.ReadLine();
}
}
}
让我们从 `main()` 函数开始。基本上,下面一行将给出 `IUnityContainer` 的对象。
IUnityContainer unitycontainer = new UnityContainer();
然后,我们将注册主类所依赖的类。在我们的示例中,我们说 `Student` 类依赖于 `University` 类。因此,我们需要将 `University` 类添加到容器中。
unitycontainer.RegisterType<IUniversity, University>();
现在容器已准备就绪,可以解决其他类的依赖关系了。我们现在将创建一个 `Student` 类的对象,并使用 IoC 容器解决其依赖关系,如下所示:
Student stu = unitycontainer.Resolve<Student>();
在这里,您可以看到我们创建了 `University` 类的对象并将其发送给容器,所有事情都由容器处理。上面的 `university` 类还有另外两个 DI,分别是构造函数注入和方法注入。现在您可以在控制台看到输出。
在上面的程序中,我们学习了如何使用 Unity 实现一个 IoC 容器,它非常简单灵活,并且具有可插拔的方法。
Ninject
Ninject 是 .NET 应用程序的新一代依赖注入框架。它现在已发布稳定版本。当您开发将在不同系统中重用的任何组件时,它都非常有用。Ninject 具有以下优点,使其在所有 DI 框架中非常受欢迎:
- 易于学习的 API
- 轻量级(122 KB,版本-3.0.015)
- 第二代 DI 容器
- 由于轻量级代码生成而速度更快
当您在 WCF 和 MVC 应用程序中使用它时,它将提供扩展。因此,下面的示例仍然是一个控制台应用程序,它将演示 Ninject 的易用性。
从 NuGet 包管理器下载 Ninject。
成功安装包后,您将在控制台项目中看到已添加的引用。
下面的代码片段基本上演示了用于 Ninject 依赖注入的控制台应用程序。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
namespace DependencyResolvedByNinject
{
public interface IVehicle
{
void Owns();
}
class Vehicle : IVehicle
{
public void Owns()
{
Console.WriteLine("I Owns a Car.");
}
}
public class Mohan
{
IVehicle ObjVehicle = null;
public Mohan(IVehicle tmpVehicle)
{
this.ObjVehicle = tmpVehicle;
}
public void Drive()
{
this.ObjVehicle.Owns();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
namespace DependencyResolvedByNinject
{
class Program
{
static void Main(string[] args)
{
Ninject.IKernel kernal = new StandardKernel();
kernal.Bind<IVehicle>().To<Vehicle>();
var instance = kernal.Get<Mohan>();
instance.Drive();
Console.ReadLine();
}
}
}
`IVehicle` 接口和 `Vehicle` 类非常直接,我们在 `IVehicle` 接口中定义了 `Owns()` 函数,并在 `Vehicle` 类中实现了它。
现在,在“`Mohan`”类中(类名是故意的,因为我想将该类用作 `Vechicle`)。
为了使类解耦,我们实现了函数注入。`Drive()` 函数将内部调用 `Own()` 函数,该函数已在 `Vehicle` 类中定义。
让我们从 `main` 函数开始。下面一行将创建 `kernel` 类。Kernel 是 Ninject 的核心。
Ninject.IKernel kernal = new StandardKernel();
在下面一行,我们将接口绑定到相应的类。
kernal.Bind<IVehicle>().To<Vehicle>();
在下面两行中,我们正在解决 `Mohan` 类对 `Vehicle` 类的依赖关系,然后我们调用 `Drive()` 函数。
var instance = kernal.Get<Mohan>();
instance.Drive();
我们在 `Mohan` 类中执行 `Drive()` 函数,其中 `Mohan` 类依赖于 `Vehicle` 类,而无需创建 `Vehicle` 类的对象。
我们将与 `IVehicle` 接口关联的 `Vehicle` 类绑定到 IoC 容器,IoC 容器负责处理其余的事情。控制台输出显示以下消息:
Autofac
市面上有许多 IoC 容器,Autofac 是其中之一。为了使我们的架构解耦,我们必须使用任何 IoC 容器。下面是 Autofac IoC 容器的示例。在此,我们将演示通过构造函数和属性进行依赖注入。它是开源的,在 Google Code 上开发,具有以下优点:
- 提供商业支持
- 易于学习的 API
从 NuGet 包管理器下载 Autofac 包并安装到您的应用程序中。
当 NuGet 包管理器成功安装包后,您的项目中就会显示该引用。
我创建了两个接口和对应的具体类,其中包含方法定义。`QueueService` 是我们将通过构造函数和属性注入依赖的类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
namespace QueueServiceByAutofac
{
public interface IPushServive
{
void Execute();
}
public class PushServive : IPushServive
{
public void Execute()
{
Console.WriteLine("An item is pushed in to the Queue.");
}
}
public interface IPopService
{
void Execute();
}
public class PopService : IPopService
{
public void Execute()
{
Console.WriteLine("An item is pop out in to the Queue.");
}
}
class QueueService
{
public IPushServive ObjPushSerivce = null;
public IPopService ObjPopService = null;
//injection through constructor
public QueueService(IPushServive tmpService)
{
ObjPushSerivce = tmpService;
}
//Injection through property
public IPopService SetPopService
{
set { ObjPopService = value; }
}
public void Process()
{
ObjPushSerivce.Execute();
ObjPopService.Execute();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
namespace QueueServiceByAutofac
{
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<PushServive>().As<IPushServive>();
builder.RegisterType<PopService>().As<IPopService>();
var container = builder.Build();
container.Resolve<IPushServive>().Execute();
container.Resolve<IPopService>().Execute();
Console.ReadLine();
}
}
}
然后,我们实现了一个 `QueueService` 类,该类依赖于 `PushService` 和 `PopService`。控制台输出如下:
因此,上面的示例演示了如何使用 DI,并且它们在您想在应用程序开发期间选择 IoC 容器时真正提供了便利。因此,最终的选择取决于您要使用什么。POC 代码库 `DependencyInjections.zip` 已随本文一起提供。
历史
- 2015 年 12 月 3 日:初始版本