• 【读书笔记】Ninject 在MVC5中的使用


        从MVC3中就开始接触Ninject这个IOC工具。也一直是MVC Framework系列书籍中推荐的IOC工具,当然还有优秀的Autofac等。性能和使用上面个有千秋。下面先看一下Ninject的使用: 

        1.添加Ninject。工具-->Nuget程序包管理器-->程序包管理器控制台,输入下面的命令:

    Install-Package Ninject -version 3.0.1.10
    Install-Package Ninject.Web.Common -version 3.0.0.7
    Install-Package Ninject.MVC3 -Version 3.0.0.6

       

      2.创建依赖分解器 NinjectDependencyResolver。

        NinjectDependencyResolver实现了IDependencyResolver接口,当一个请求进来的时候,MVC框架会调用GetService或GetServices方法去获取对象的实例去服务这个请求。GetAll方法支持单个类型的多重绑定。我们在AddBinds方法中添加接口的绑定。

     public class NinjectDependencyResolver : IDependencyResolver
        {
            private IKernel kernel;
            public NinjectDependencyResolver(IKernel kernelParam)
            {
                kernel = kernelParam;
                AddBindings();
            }
            public object GetService(Type serviceType)
            {
                return kernel.TryGet(serviceType);
            }
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return kernel.GetAll(serviceType);
            }
            private void AddBindings()
            {   

                   kernel.Bind<IProductRepository>().To<EFProductRepository>();
                   kernel.Bind<IAuthProvider>().To<FormsAuthProvider>();

            }
        }

    3.注册

     在MVC3,4中,我们是在Global的Application_Start()中注册。当应用启动的时候回触发Application_Start()中的方法。

     DependencyResolver.SetResolver(new NinjectDependencyResolver());

     那再MVC5中,更加完善。注意到我们之前引用了Ninject.Web.Common,这个是在MVC4以前没有出场的。它会在App_Start文件中创建一个NinjectWebCommon.cs类:

     它的Start方法是会先于Global的Application_Start()方法执行。

    [assembly: WebActivator.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
    [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(NinjectWebCommon), "Stop")]
    namespace SportsStore.WebUI
    {
        public static class NinjectWebCommon 
        {
            private static readonly Bootstrapper bootstrapper = new Bootstrapper();
            /// <summary>
            /// Starts the application
            /// </summary>
            public static void Start() 
            {
                DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
                DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
                bootstrapper.Initialize(CreateKernel);
            }
            
            /// <summary>
            /// Stops the application.
            /// </summary>
            public static void Stop()
            {
                bootstrapper.ShutDown();
            }
            
            /// <summary>
            /// Creates the kernel that will manage your application.
            /// </summary>
            /// <returns>The created kernel.</returns>
            private static IKernel CreateKernel()
            {
                var kernel = new StandardKernel();
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
           
                RegisterServices(kernel);
                return kernel;
            }
    
            /// <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 Infrastructure.NinjectDependencyResolver(kernel));
            }        
        }
    }

      它充分使用Asp.Net 4.0的新技术,并使用了WebActivator框架,在Web程序启动前动态调用Start函数,在关闭前调用Stop函数.在Start函数中,动态注册了OnePerRequestHttpModule和NinjectHttpModule.而对于CreateKernel函数,首先新建了IOC核心,然后绑定了Func<IKernel>类型与IHttpModule类型.

      5.绑定方法:

       1)基本绑定

    kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();

      2)传递参数:

      创建一个IDiscountHelper接口。让DefaultDiscountHelper 实现它。

    public interface IDiscountHelper {
    decimal ApplyDiscount(decimal totalParam);
    }
    public class DefaultDiscountHelper : IDiscountHelper {
    public decimal DiscountSize { get; set; }
    public decimal ApplyDiscount(decimal totalParam) {
    return (totalParam - (DiscountSize / 100m * totalParam));
    }
    View Code
    kernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize", 50M);

    也可以从构造函数传递参数:

    public class DefaultDiscountHelper : IDiscountHelper {
    public decimal discountSize;
    public DefaultDiscountHelper(decimal discountParam) {
    discountSize = discountParam;
    }
    public decimal ApplyDiscount(decimal totalParam) {
    return (totalParam - (discountSize / 100m * totalParam));
    }
    }
    kernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discountParam", 50M);

     3)条件绑定

     有时候我们一个接口,有不同的实现对象。这个时候我们需要根据使用情况来获取相应的实例。我们再创建一个FlexibleDiscountHelper来实现上面的接口。

    public class FlexibleDiscountHelper : IDiscountHelper {
    public decimal ApplyDiscount(decimal totalParam) {
    decimal discount = totalParam > 100 ? 70 : 25;
    return (totalParam - (discount / 100m * totalParam));
    }
    }
    kernel.Bind<IDiscountHelper>().To<FlexibleDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();

     上面的意思就是:当注入到LinqValueCalculator的时候,绑定FlexibleDiscountHelper。这样就方便多了。

    方法
    效果
    When(predicate)
    当Lambda表达式结果为ture时使用该绑定
    WhenClassHas<T>()
    当被注入的对象被特性T标记时使用该绑定
    WhenInjectedInto<T>()
    当被注入的对象是T时使用绑定。

     4)作用范围

    kernel.Bind<IValueCalculator>().To<LinqValueCalculator>().InRequestScope();

    InRequestScope是一个扩展方法,位于Ninject.Web.Common命名空间中,告诉Ninject,只应该为每一个Asp.Net 接受到的Http请求创建一个LinqValueCalculator实例。

    方法
    效果
    InTransientScope()
    默认模式,解决每次依赖的时候都会创建一个新实例。
    InSingletonScope()
    单例模式,贯穿整个应用。
    ToConstant(object)
    绑定到某个常亮。
    InThreadScope()
    对于单个线程创建单个实例
    InRequestScope()
    对于单个Http请求创建单个实例

     这里说明下ToConstant,对于某个接口,我们实现好了一个对象,可以用ToConstant方法来绑定

     比如我们用moq实现了接口IProductRepository,这样在使用到这个接口的地方,注入的实例中就已经含有了三个Product对象,相当于已经初始化好了。

      var mock=new Mock<IProductRepository>();
                mock.Setup(m => m.Products).Returns(new List<Product>
                {
                    new Product {Name = "Football", Price = 25},
                    new Product {Name = "Surf board", Price = 179},
                    new Product {Name = "Running shoes", Price = 95}
                });
                
      kernel.Bind<IProductRepository>().ToConstant(mock.Object);

    小结:IOC在MVC中应用的很多,有必要选择一款适合自己需要的IOC框架。希望本文对你有帮助。

    参考文章:NinJect 源码分析: http://www.verydemo.com/demo_c360_i40786.html

                  IOC 框架性能比较:http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html

                  小牛之路 Ninject:http://www.cnblogs.com/willick/p/3299077.html

    阅读书籍:Apress Pro Asp.Net MVC5  

     

  • 相关阅读:
    Introduction to Mathematical Thinking
    学习 Unix 常用命令
    学习 《UNIX网络编程》
    学习编译并运行C代码
    Introduction to Mathematical Thinking
    Introduction to Mathematical Thinking
    CentOS 6和CentOS 7防火墙的关闭
    centOS 7下无法启动网络(service network start)错误解决办法(应该是最全的了。。。)
    虚拟机中的CentOS 7设置固定IP连接最理想的配置
    使用VMware安装CentOS7详请
  • 原文地址:https://www.cnblogs.com/stoneniqiu/p/4594642.html
Copyright © 2020-2023  润新知