[转载]Asp.net MVC源码分析–Asp.net MVC与Ninject.MVC集成分析 – 十一月的雨 – 博客园.
在之前的文章中我们分析了DependencyResolver 与 Service location. 可以利用DependencyResolver 来注册我们自己的IResolver实现,从而改变框架的行为.在Niject.MVC 中正是利用这个机制来实现了一套Service location机制,来创建Controller.
Niject.MVC 源码的下载地址是: https://github.com/ninject/ninject.web.mvc
——————————————————————————————
首先我们找到NinjectMVC3.cs 文件,所有引入Niject.MVC dll 的ASP.NET MVC项目都需要这个类
1 #if NUGET 2 [assembly: WebActivator.PreApplicationStartMethod(typeof(SampleApplication.App_Start.NinjectMVC3), "Start")] 3 [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(SampleApplication.App_Start.NinjectMVC3), "Stop")] 4 5 namespace SampleApplication.App_Start 6 { 7 using System.Reflection; 8 using Microsoft.Web.Infrastructure.DynamicModuleHelper; 9 using Ninject; 10 using Ninject.Web.Mvc; 11 12 public static class NinjectMVC3 13 { 14 private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 15 16 /// <summary> 17 /// Starts the application 18 /// </summary> 19 public static void Start() 20 { 21 DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule)); 22 DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule)); 23 bootstrapper.Initialize(CreateKernel); 24 } 25 26 /// <summary> 27 /// Stops the application. 28 /// </summary> 29 public static void Stop() 30 { 31 bootstrapper.ShutDown(); 32 } 33 34 /// <summary> 35 /// Creates the kernel that will manage your application. 36 /// </summary> 37 /// <returns>The created kernel.</returns> 38 private static IKernel CreateKernel() 39 { 40 var kernel = new StandardKernel(); 41 RegisterServices(kernel); 42 return kernel; 43 } 44 45 /// <summary> 46 /// Load your modules or register your services here! 47 /// </summary> 48 /// <param name="kernel">The kernel.</param> 49 private static void RegisterServices(IKernel kernel) 50 { 51 kernel.Load(Assembly.GetExecutingAssembly()); 52 } 53 } 54 } 55 #endif
我们看到当Assembly 加载后会调用WebActivator 的StartMethod方法来,启动NinjectMVC3.Start方法这个方法中调用了bootstrapper.Initialize方法.
1 public class Bootstrapper: IBootstrapper 2 { 3 /// <summary> 4 /// The ninject kernel of the application 5 /// </summary> 6 protected static IKernel kernelInstance; 7 8 /// <summary> 9 /// Gets the kernel. 10 /// </summary> 11 [Obsolete("Do not use Ninject as Service Locator")] 12 public IKernel Kernel 13 { 14 get { return kernelInstance; } 15 } 16 17 /// <summary> 18 /// Starts the application. 19 /// </summary> 20 /// <param name="createKernelCallback">The create kernel callback function.</param> 21 public void Initialize(Func<IKernel> createKernelCallback) 22 { 23 if (kernelInstance != null) 24 { 25 throw new InvalidOperationException("Already Initialized!"); 26 } 27 28 kernelInstance = createKernelCallback(); 29 30 kernelInstance.Bind<IResolutionRoot>().ToConstant(kernelInstance); 31 kernelInstance.Bind<IDependencyResolver>().To<NinjectDependencyResolver>(); 32 kernelInstance.Bind<IFilterProvider>().To<NinjectFilterAttributeFilterProvider>(); 33 kernelInstance.Bind<IFilterProvider>().To<NinjectFilterProvider>(); 34 kernelInstance.Bind<RouteCollection>().ToConstant(RouteTable.Routes); 35 kernelInstance.Bind<HttpContext>().ToMethod(ctx => HttpContext.Current).InTransientScope(); 36 kernelInstance.Bind<HttpContextBase>().ToMethod(ctx => new HttpContextWrapper(HttpContext.Current)).InTransientScope(); 37 kernelInstance.Bind<ModelValidatorProvider>().To<NinjectDataAnnotationsModelValidatorProvider>(); 38 39 ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single()); 40 DependencyResolver.SetResolver(CreateDependencyResolver()); 41 RemoveDefaultAttributeFilterProvider(); 42 } 43 44 /// <summary> 45 /// Initializes a HttpApplication instance. 46 /// </summary> 47 /// <param name="httpApplication">The HttpApplication instance.</param> 48 public void InitializeHttpApplication(HttpApplication httpApplication) 49 { 50 kernelInstance.Inject(httpApplication); 51 } 52 53 /// <summary> 54 /// Releases the kernel on application end. 55 /// </summary> 56 public void ShutDown() 57 { 58 if (kernelInstance != null) 59 { 60 kernelInstance.Dispose(); 61 kernelInstance = null; 62 } 63 } 64 65 /// <summary> 66 /// Creates the controller factory that is used to create the controllers. 67 /// </summary> 68 /// <returns>The created controller factory.</returns> 69 private static IDependencyResolver CreateDependencyResolver() 70 { 71 return kernelInstance.Get<IDependencyResolver>(); 72 } 73 74 /// <summary> 75 /// Removes the default attribute filter provider. 76 /// </summary> 77 private static void RemoveDefaultAttributeFilterProvider() 78 { 79 var oldFilter = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider); 80 FilterProviders.Providers.Remove(oldFilter); 81 } 82 }
在这Initialize方法中向kernel容器注入了很多接口的实现.并且向DependencyResolver中注册了Ninject的IDependencyResolver实现
DependencyResolver.SetResolver(CreateDependencyResolver());
最后我们就可以向Ninject注入所有MVC 框架中依赖DependencyResolver获取接口的实现.
并且当我们的Controller 的构造函数中有接口参数,并且在Ninject有注册的话,也可以顺利的创建Controller的参数中的接口(因为所有Controller的创建都通过Ninject),这样我们就可以把Controller中的一些业务行为抽取出来创建独立的类(业务层),从而划分出更清晰的类的层次结构和设计.
例如:
1 public class AccountController : Controller 2 { 3 4 private IAccountManater _accountManager; 5 6 public AccountController (IAccountManater accountManager) 7 8 { 9 10 _accountManager = accountManager; 11 12 } 13 14 [HttpPost] 15 public ActionResult LogOn(LogOnModel model, string returnUrl) 16 { 17 18 if(_accountManager.Has(model)) 19 20 return view("ok"); 21 22 else 23 24 return view("error"); 25 } 26 27 }
这时只要我们在Application_Strat 中向Iinject容器中注册IAccountManager 的实现AccountController就可以使用了.