zoukankan      html  css  js  c++  java
  • 依赖注入:Ninject学习笔记

    依赖注入(DI)就不多说了,可以自行百度,本笔记整理自Pro ASP.NET MVC5。

    1,Ninject安装

    Ninject是一个开源的注入容器,可以通过VS的Nuget进行安装。由于是在mvc中应用,需要安装下面3个类库。

    • Ninject
    • Ninject.Web.Common
    • Ninject.Web.Mvc

    2,简单使用

    在没有用DI之前,我们通常是这样写的。

            // GET: Home
            public ActionResult Index()
            {
                IValueCalculator calc = new LinqValueCalculator();
    
                ShoppingCart cart = new ShoppingCart(calc);
                cart.Products = products;
    
                decimal totalValue = cart.CalulateProductTotal();
    
                return View(totalValue);
            }

    我们的目标是,不去new LinqValueCalculator,这样才会消除依赖,于是利用Ninject变成下面这样。

            public ActionResult Index()
            {
    
                IKernel ninjectKernel = new StandardKernel();
                ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
                IValueCalculator calc = ninjectKernel.Get<IValueCalculator>();
    
                ShoppingCart cart = new ShoppingCart(calc);
                cart.Products = products;
    
                decimal totalValue = cart.CalulateProductTotal();
    
                return View(totalValue);
            }

    简单的3句代码,建立起了IValueCalculator和LinqValueCalculator之间的映射关系,然后调用Get方法获得实例。

    这样做了之后,我们就不用再new了,但是这远远不够,Controler类中依然存在LingValueCalculator和额外的Ninject的类,

    我们需要把这些代码移出Controler类。

    3,改进Ninject,达到真正的解耦

    1)在Controler的构造函数中传入IValueCalculator

        public class HomeController : Controller
        {
            private IValueCalculator calc;
            private Product[] products = {
                new Product {Name = "Kayak", Category = "Watersports", Price = 275M },
                new Product {Name = "Lifejacket", Category = "Watersports", Price = 48.95M },
                new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.5M },
                new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M }
            };
    
            public HomeController(IValueCalculator calc)
            {
                this.calc = calc;
            }
    
            // GET: Home
            public ActionResult Index()
            {
                ShoppingCart cart = new ShoppingCart(calc);
                cart.Products = products;
    
                decimal totalValue = cart.CalulateProductTotal();
    
                return View(totalValue);
            }
        }

    难道构造函数中的IValueCalculator会自动初始化?是的,这就是Ninject帮你做的,但必须先按照下面这样做。

    2)实现IDependecyResolver接口,这个接口是MVC自带的,不是Ninject的。实现了这个接口,MVC框架才会自动按照上面那样创建对应接口的实例。

        public class NinjectDependencyResolver : IDependencyResolver
        {
            private IKernel kernal;
    
            public NinjectDependencyResolver(IKernel kernalParam)
            {
                kernal = kernalParam;
                AddBindings();
            }
            public object GetService(Type serviceType)
            {
                return kernal.TryGet(serviceType);
            }
    
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return kernal.GetAll(serviceType);
            }
    
            public void AddBindings()
            {
                kernal.Bind<IValueCalculator>().To<LinqValueCalculator>().InRequestScope();
                kernal.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discount", 10m);
                kernal.Bind<IDiscountHelper>().To<FlexibleDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();
            }
        }

    GetService和GetServices是接口的方法,大致就是传入一个接口类型,然后传出去一个实例。

    你完全可以自己简单的实现这两个方法,但是Ninject毕竟是经受了考验的,各种配置齐全的DI容器,本文的主旨也就是介绍Ninject,所以用Ninject实现这两个方法。

    具体就是上面这样,所有的映射关系放在了AddBinding这个方法中,以后只用修改这个方法,就可以全局改变不同的实现。

    3)NinjectDependencyResolver的初始化

    上面的这个NinjectDependencyResolver需要初始化,在添加Njinect类库的时候,在App_Start下,生成了一个NinjectWebCommon.cs文件,其中有一个RegisterServices方法,

    这个方法会在应用程序初始化的时候调用,所以我们就在这里初始化我们的NinjectDependencyResolver。

        public static class NinjectWebCommon 
        {
          。。。
            /// <summary>
            /// Load your modules or register your services here!
            /// </summary>
            /// <param name="kernel">The kernel.</param>
            private static void RegisterServices(IKernel kernel)
            {
                System.Web.Mvc.DependencyResolver.SetResolver(new
                    EssentialTools.Infrastructure.NinjectDependencyResolver(kernel));
            }
        }

    好了,到此为止,我们就可以在Controler这个类的构造函数任意的传人需要使用的接口,只要在NinjectDependencyResolver中添加对应的映射,Ninject就会自动的帮我们创建好。

    4)Ninject不是简单的new,它可以在建立映射的时候配置不同的选项,下面例举几个重要的配置选项。

    • 创建对象的生命周期的控制
    kernal.Bind<IValueCalculator>().To<LinqValueCalculator>().InRequestScope();
    • 创建对象的构造函数参数的设置(属性值也可以设置)
    kernal.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discount", 10m);
    • 建立的映射的适用条件
    kernal.Bind<IDiscountHelper>().To<FlexibleDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();
    • 实例初始化时,又依赖于其他接口时,Ninject会把依赖的所有接口一并初始化,这一点我们自己实现的话可能会比较困难。

    以上就是Ninject的简单介绍,更加详尽的功能,可以查阅相关文档。另外,微软自带的Utinity也是和Ninject相似的DI容器,有了Ninject的使用经验,

    再用其他的DI容器应该也不是很困难。

  • 相关阅读:
    使用 lntelliJ IDEA 创建 Maven 工程的springboot项目
    HTTP协议小记
    TCP/UDP的网络底层实现
    TCP的三次握手和四次挥手
    IP地址和MAC地址绑定的必要性
    什么是回调函数?
    基于TCP实现的Socket通讯详解
    HTTP协议随笔
    计算机虚拟世界的入门常识(1)——信号的原理
    UDP比TCP好用的优势
  • 原文地址:https://www.cnblogs.com/xiashengwang/p/7929378.html
Copyright © 2011-2022 走看看