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项目都需要这个类

View Code
 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方法.

View Code
 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中的一些业务行为抽取出来创建独立的类(业务层),从而划分出更清晰的类的层次结构和设计.

例如:

View Code
 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就可以使用了.

 

转载请注明出处:http://www.cnblogs.com/RobbinHan/archive/2011/12/05/2270707.html 

本文作者: 十一月的雨 http://www.cnblogs.com/RobbinHan

posted @ 2011-12-01 16:11  十一月的雨  阅读(1925)  评论(0编辑  收藏  举报