[转载]Asp.net MVC源码分析--Asp.net MVC与Ninject.MVC集成分析

[转载]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就可以使用了.

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏