在MVC5中的使用Ninject

在MVC5中的使用

Ninject

从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 实现它。

 

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-24 15:27:27

在MVC5中的使用Ninject的相关文章

【读书笔记】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 In

【转】MVC5中的区域(Areas)

MVC本身提倡的就是关注点分离.但是当项目本身的业务逻辑足够复杂,如果所有的业务逻辑都写个Controller文件夹下面的时候,你会看到非常庞大的各种命名的Controller,这个时候区域的作用就非常明显了,将不同的模块通过区域加以区分,简单明了. 添加区域: 新建的MVC工程是没有区域的.点击项目右键->添加->区域,输入区域名称..net会自动在项目下添加"Areas"文件夹,并在该文件夹下创建对应的区域的文件夹.创建一个"test"的区域,在区域

在ASP.NET MVC5 中使用 FormsAuthenticationTicket 的注意事项

在根目录 web.confgi文件中添加如下配置信息. <configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> </system.web> </configuration

MVC5中Model层开发数据注解

ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证(在服务器端和客户端验证数据的有效性) 数据显示(在View层显示相应的数据) 数据注解相关的命名空间如下: System.ComponentModel.DataAnnotations System.ComponentModel.DataAnnotations.Schema System.Web.Mvc System.Web.Securit

MVC5中路由新特性

1.什么是Attribute路由?怎么样启用Attribute路由? 微软在 ASP.NET MVC5 中引入了一种新型路由:Attribute路由,顾名思义,Attribute路由是通过Attribute来定义路由.当然,MVC5也支持以前定义路由的方式,你可以在一个项目中混合使用这两种方式来定义路由. 在以前的版本中我们通常在 RouteConfig.cs 文件中通过以下方式来定义路由: routes.MapRoute( name: "ProductPage", url: &quo

MVC5中后台提供Json,前台处理Json,绑定给Dropdownlist的例子

MVC5中后台提供Json,前台处理Json,绑定给Dropdownlist的例子: 前端: 我们以前在前端定义了两个控件: <div class="row"> <div class="col-md-1">国家</div> <div class="col-md-11"> @Html.DropDownListFor(model => model.Director.HometownID, MvcE

MVC5中使用KinEditor

参考:http://www.cnblogs.com/weicong/archive/2012/03/31/2427608.html 第一步 将 KindEditor 的源文件添加到项目中,建议放到 /Scripts/kindeditor 目录中,其中只需要有 lang目录.plugis目录.themes目录和kindeditor-min.js文件即可. 第二步 通过js讲textarea绑定到kineditor. <textarea id="HD_Content" rows=&q

MVC5中Model设置属性注解

ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证(在服务器端和客户端验证数据的有效性) 数据显示(在View层显示相应的数据) 数据注解相关的命名空间如下: System.ComponentModel.DataAnnotations System.ComponentModel.DataAnnotations.Schema System.Web.Mvc System.Web.Securit

在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView

背景 在前一篇文章<[初学者指南]在ASP.NET MVC 5中创建GridView>中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web 表单的功能.通过前文,我们已经了解到使用 jQuery 插件的数据表可以很容易地实现具有搜索.排序和分页等重要功能的表格. 前文中需要注意的是,所有通过插件实现的特性都是客户端的,这意味着所有的数据都首先在页面载入,然后由插件来处理客户端搜索.分页和排序的数据.如果数据表不是特别大,这么做是可以的:但是,如