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

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.29/5 (19投票s)

2015 年 12 月 3 日

CPOL

5分钟阅读

viewsIcon

91054

downloadIcon

566

本文主要比较了 .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 日:初始版本

 

© . All rights reserved.