【讀書筆記】Ninject 在MVC5中的使用

    從MVC3中就開始接觸Ninject這個IOC工具。也一直是MVC Framework系列書籍中推薦的IOC工具,固然還有優秀的Autofac等。性能和使用上面個有千秋。下面先看一下Ninject的使用: html

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

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。app

    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>();ide

        }
    }

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類型.spa

  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  

 

相關文章
相關標籤/搜索