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,你应该检查它们。