Ninject 依賴注入

依賴性解析器用於避免緊密耦合的類,提高靈活性並使測試變得容易。你可以建立自己的依賴注入器(不推薦)或使用編寫良好且經過測試的依賴注入器之一。在這個例子中,我將使用 Ninject

第一步:建立依賴解析器

首先,從 NuGet 下載 Ninject 。建立名為 Infrastructure 的資料夾並新增名為 NinjectDependencyResolver 的類 :

using Ninject;
using System;
using System.Collections.Generic;
using System.Web.Mvc;

public class NinjectDependencyResolver
    : IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver()
    {
        // Initialize kernel and add bindings
        kernel = new StandardKernel();
        AddBindings();
    }

    public object GetService(Type serviceType)
    {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.GetAll(serviceType);
    }

    private void AddBindings()
    {
        // Bindings added here
    }
}

當 MVC 框架需要一個類的 insance 來為傳入的請求提供服務時,它將呼叫 GetServiceGetServices 方法。

第二步:註冊依賴解析器

現在我們有自定義依賴項解析器,我們需要註冊它以告訴 MVC 框架使用我們的依賴項解析器。在 Global.asax.cs 檔案中註冊依賴項解析器 :

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    DependencyResolver.SetResolver(new NinjectDependencyResolver());
    
    // .....
}

第三步:新增繫結

想象一下,我們有以下介面和實現:

public interface ICustomCache
{
    string Info { get; }
}

public class CustomCache : ICustomCache
{
    public string Info
    {
        get
        {
            return "Hello from CustomCache.";
        }
    }
}

如果我們想在我們的控制器中使用 CustomCache 而不將我們的控制器與 CustomCache 緊密耦合,那麼我們需要將 ICustomCache 繫結到 CustomCache 並使用 Ninject 注入它。第一件事首先,結合 ICustomCache 到 CustomCache 通過新增以下程式碼來 AddBindings() 的方法 NinjectDependencyResolver

private void AddBindings()
{
    // Bindings added here
    kernel.Bind<ICustomCache>().To<CustomCache>();
}

然後準備你的注​​射控制器,如下所示:

public class HomeController : Controller
{
    private ICustomCache CustomCache { get; set; }

    public HomeController(ICustomCache customCacheParam)
    {
        if (customCacheParam == null)
            throw new ArgumentNullException(nameof(customCacheParam));

        CustomCache = customCacheParam;
    }

    public ActionResult Index()
    {
        // cacheInfo: "Hello from CustomCache."
        string cacheInfo = CustomCache.Info;

        return View();
    }
}

這是建構函式注入的示例,它是依賴注入的一種形式。如你所見,我們的 Home 控制器不依賴於 CustomCache 類 itslef。如果我們想在我們的應用程式中使用另一個 ICustomCache,我們唯一需要改變的是將 ICustomCache 繫結到另一個實現,這是我們需要採取的唯一步驟。這裡發生的事情是,MVC 框架要求我們註冊的依賴項解析器通過 GetService 方法建立 HomeController 類的例項。GetService 方法請求 Ninject 核心建立請求的物件,Ninject 核心檢查其術語中的型別,並發現 HomeController 的建構函式重新獲取 ** ICustomCache 並結合已新增 ICustomCache 。Ninject 建立繫結類的例項,使用它建立 HomeController 並返回它 MVC Framework。

依賴鏈

當 Ninject 嘗試建立型別時,它會檢查型別和其他型別之間的其他依賴關係,如果有任何 Ninject 也嘗試建立它們。例如,如果我們的 CustomCache 類需要 ICacheKeyProvider,並且如果為 ICacheKeyProvider 新增了 bining,Ninject 可以為我們的類提供它。

ICacheKeyProvider 介面和 SimpleCacheKeyProvider 實現:

public interface ICacheKeyProvider
{
    string GenerateKey(Type type);
}

public class SimpleCacheKeyProvider
    : ICacheKeyProvider
{
    public string GenerateKey(Type type)
    {
        if (type == null)
            throw new ArgumentNullException(nameof(type));

        return string.Format("{0}CacheKey", type.Name);
    }
}

修改了 CustomCache

public class CustomCache : ICustomCache
{
    private ICacheKeyProvider CacheKeyProvider { get; set; }

    public CustomCache(ICacheKeyProvider keyProviderParam)
    {
        if (keyProviderParam == null)
            throw new ArgumentNullException(nameof(keyProviderParam));

        CacheKeyProvider = keyProviderParam;
    }

    ...........
}

ICacheKeyProvider 新增繫結 :

private void AddBindings()
{
    // Bindings added here
    kernel.Bind<ICustomCache>().To<CustomCache>();
    kernel.Bind<ICacheKeyProvider>().To<SimpleCacheKeyProvider>();
}

現在,當我們導航到 HomeController 時, Ninject 會建立 SimpleCacheKeyProvider 的例項,使用它來建立 CustomCache 並使用 CustomCache 例項來建立 HomeController

Ninject 有很多很棒的功能,如連結依賴注入,如果你想使用 Ninject,你應該檢查它們。