【读书笔记】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));
}

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

时间: 2024-10-16 02:52:58

【读书笔记】Ninject 在MVC5中的使用的相关文章

linq读书笔记2-查询内存中的对象

上次我们说到了linq对数组内容的检索,自.net2.0以后,泛型成了很常见的一种应用技术,linq对泛型的检索也提供了完善的支持 如对list类型的支持,范例如下: class Program    {        static void Main(string[] args)        {            List<Books> samplebooks = new List<Books>() {                                    

《游戏引擎架构》读书笔记1-游戏引擎中的C++

3月底,我暂时结束了北京的工作,从原来的公司离职,主要是为了学习游戏开发的底层知识和3D引擎相关的内容,并进行技术转型,为了鞭策自己的学习,未来博客更新会比较频繁,现阶段主要是<游戏引擎架构>读书笔记系列和unity学习笔记系列. <游戏引擎架构>在两年前就买了,而且自己也大体的看过一遍,因为自己想学习引擎的底层知识,所以重新又找出了这本书再读一遍,并把根据自己的理解写一些读书笔记在这里与大家交流,另外因为想有一个新的开始,近期都会在博客园这里写技术博客了,前些日子搞了个自己的网站

读书笔记--关于Cocoa框架中的类

Chapter 10 Cocoa Classes iOS编程时, 实际是进行Cocoa编程. 所以必须熟悉Cocoa, 必须知道Cocoa是什么, 它能够做什么, 你和Cocoa如何进行"交流". Cocoa是一个庞大的Framework, 被分割成若干较小的Framework. 任何iOS编程人员都需要花费一定时间来熟练Cocoa. Cocoa中含有一些主要的规则和组件, 最好是以它们为主线来学习Cocoa. Cocoa大部分类都是OC写的, 虽然OC类和Swift类能相互转换.但S

Java读书笔记十一(Java中的内省机制)

1.前言 最近在学习Java的时候,突然发现了这个概念,鉴于好奇心的压迫,于是打算写一篇博客来总结一下. 2.什么是内省机制 为了让程序员们更好的从左Java对象的属性,SUN公司开发了一套API,就被我们称为"内省",有利于我们对类对象的属性的操作,减少了代码的数量. 3.内省和反射有什么区别 反射式在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态. 内省机制是通过反射来实现的,BeanInfo用来暴露一个b

Oracle性能诊断艺术-读书笔记(执行计划中显示 Starts, E-Rows, REM A-Rows and A-Time)等)

【读书笔记】iOS-属性中的内存管理参数

一,assign 代表设置时候直接赋值,而不是复制或者保留它. 二,retain. 会在赋值的时候把新值保留.此属性只能用于Object-C对象类型. 三,copy 在赋值时,将新值复制一份,复制工作由copy执行,此属性只对那些实行了NSCopying协议的对象类型有效. 参考资料:<iPhone与iPad开发实战-iOS经典应用剖析> 原文地址:https://www.cnblogs.com/yang-guang-girl/p/8445996.html

《学会提问》读书笔记二

<学会提问>读书笔记二 因为书中的小点知识和思考太多,我从这篇笔记开始就只记我害怕会遗忘的知识,思考过程就不提及了. 弱势批判性思维和强势批判性思维 弱势批判性思维的目的是用批判性思维来反驳.抵制那些和你意见不同的论述最终就是为了看到那些与你主张不一致的人服服帖帖的甘心认输,但是这样就意味着,你对于是否接近真理和发扬美德漠不关心,实际上也摧毁了批判性思维潜在的人性的一面和不断发展进步的特征.而且我认为,弱势批判性思维的出发点是自私的,他们盲目地认为自己的观点就是正确的,用批判性思维来批判其他人

《C陷阱与缺陷》读书笔记

<C陷阱与缺陷>读书笔记 1.编译器中的词法分析器负责将程序分解为一个个符号.C语言中,符号之间的空白 (包括Space ,Tab , Enter) 都将被忽略,但一个符号的中间不能有空白,否则可能被解释成为另一个或几个符号. 2.编译器将程序分解成符号的方法是从左到右逐个字符读入,如果该字符可能会组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分:如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已经不再可能组成一个有意义的

《Linux内核设计与实现》Chapter 5 读书笔记

<Linux内核设计与实现>Chapter 5 读书笔记 在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口,这些接口的作用是: 使应用程序受限地访问硬件设备 提供创建新进程与已有进程进行通信的机制 提供申请操作系统其他资源的能力 一.与内核通信 1.系统调用的作用 系统调用在用户空间进程和硬件设备之间添加了一个中间层,作用是: 为用户空间提供了一种硬件抽象接口: 系统调用保证了系统的稳定和安全,即可以避免应用程序不正确地使用硬件设备,窃取其他进程的资源: 每个进程都运行在虚拟系统中