1. 程式人生 > >Ninject依賴注入——建構函式、屬性、方法和欄位的注入(三)

Ninject依賴注入——建構函式、屬性、方法和欄位的注入(三)

1、Ninject簡介

  Ninject是基於.Net平臺的依賴注入框架,它能夠將應用程式分離成一個個高內聚、低耦合(loosely-coupled, highly-cohesive)的模組,然後以一種靈活的方式組織起來。Ninject可以使程式碼變得更容易編寫、重用、測試和修改。

2、專案引用Ninject

1>、 Tools -> Libaary Package Manager -> Package Manager Console,開啟Package Manager Console視窗;

2>、在Package Manager Console視窗中輸入指令,Enter;

1 PM> Install-Package Ninject

3>、在專案中新增對Ninject的引用。

3、Ninject使用Modules and the Kernel注入

  Ninject中將類別以模組(Module)形式進行分組繫結,每一個模組代表應用程式的一個獨立部分,這些模組可以根據需要進行組織。每一個模組都需要實現介面IModule,多數採用擴充套件StandardModule類來便捷實現。

  Ninject依賴注入包括建構函式、屬性、方法和欄位的依賴注入。以下先通過建構函式注入方式進行說明,仍採用上節中使用的介面及類。

1>、Ninject建構函式依賴注入(Constructor Injection)

武器介面IWeapon(IWeapon.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NInjectApp
{
    /// <summary>
  /// 武器
  /// </summary>
    public interface IWeapon
    {
        void Hit(string target);
    }
}
武器類Sword(Sword.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NInjectApp
{
    /// <summary>
  /// 刀
  /// </summary>
    public class Sword : IWeapon
    {
        public void Hit(string target)
        {
            Console.WriteLine("Hit the target {0} by sword", target);
        }
    }
}
勇士類Samurai(Samurai.cs),在建構函式Samurai中新增[Inject]屬性(Attribute)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    /// <summary>
  /// 勇士
  /// </summary>
    public class Samurai
    {
        private IWeapon _weapon;

        [Inject]
        public Samurai(IWeapon weapon)
        {
            _weapon = weapon;
        }

        public void Attack(string target)
        {
            _weapon.Hit(target);
        }
    }
}
新增勇士類別繫結模組類WarriorModule(WarriorModule.cs)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject.Modules;

namespace NInjectApp
{
    public class WarriorModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IWeapon>().To<Sword>();
            Bind<Samurai>().ToSelf();
        }
    }
}
建立模組(Module)後,將它們載入到Kernel容器中。呼叫Kernel的Get()方法,獲取Ninject的類別例項。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IKernel kernal = new StandardKernel(new WarriorModule());
            //Samurai s = new Samurai(kernal.Get<IWeapon>()); // 建構函式注入
            Samurai s = kernal.Get<Samurai>();
            s.Attack("enemy");

            Console.ReadKey();
        }
    }
}
如果需要的話,也可以建立多個模組(Module),將它們引數傳遞到Kernel的建構函式中。
public class Module1 {
      public override  void Load() { ... }
}

public class Module2 {
      public override  void Load() { ... }
}

class Program {
      public static void Main()
      {
            IKernel kernel = new StandardKernel(new Module1(), new Module2(), ...);
            ...
      }
}

2>、Ninject屬性依賴注入(Property Injection)

  與建構函式注入不同,可以有多個屬性(Property)宣告[Inject] Attribute。

  修改Samurai類和Program類,其他不變。

  Samurai類注入屬性:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    /// <summary>
  /// 勇士
  /// </summary>
    public class Samurai
    {
        private IWeapon _weapon;

        /// <summary>
     /// 定義注入介面屬性
     /// </summary>
        [Inject]
        public IWeapon Weapon
        {
            get
            {
                return _weapon;
            }
            set
            {
                _weapon = value;
            }
        }

        public void Attack(string target)
        {
            _weapon.Hit(target);
        }
    }
}
Program類呼叫:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IKernel kernal = new StandardKernel(new WarriorModule());
            Samurai s = new Samurai() { Weapon = kernal.Get<IWeapon>() };// 屬性注入
            s.Attack("enemy");

            Console.ReadKey();
        }
    }
}

3>、Ninject方法注入(Method Injection)

  Ninject可以有多個方法(Method)宣告[Inject]屬性(Attribute)。

  修改Samurai類和Program類,其他不變。

  Samurai類添加註入方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    /// <summary>
  /// 勇士
  /// </summary>
    public class Samurai
    {
        private IWeapon _weapon;

        [Inject]
        public void Arm(IWeapon weapon)
        {
            _weapon = weapon;
        }

        public void Attack(string target)
        {
            _weapon.Hit(target);
        }
    }
}
 Program類呼叫注入方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IKernel kernal = new StandardKernel(new WarriorModule());
            Samurai s = new Samurai();
            s.Arm(kernal.Get<IWeapon>()); // 方法注入
            s.Attack("enemy");

            Console.ReadKey();
        }
    }
}

4>、Ninject欄位注入(Field Injection)

  Ninject可以有多個欄位(Field)宣告[Inject]屬性(Attribute),但在實際應用中儘量避免使用欄位注入。

  修改Samurai類和Program類,其他不變。

  Samurai類添加註入欄位:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    /// <summary>
  /// 勇士
  /// </summary>
    public class Samurai
    {
        [Inject]
        private IWeapon _weapon;

        public void Attack(string target)
        {
            _weapon.Hit(target);
        }
    }
}

Program類中呼叫注入欄位:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Ninject;

namespace NInjectApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IKernel kernal = new StandardKernel(new WarriorModule());
            Samurai s = new Samurai();
            s._weapon = kernal.Get<IWeapon>(); // 需將Samurai類中欄位_weapon修飾符改為public才可以訪問
            s.Attack("enemy");

            Console.ReadKey();
        }
    }
}