• 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

  • 相关阅读:
    选项卡
    使用script创建标签添加属性值和添加样式
    判断表单不能为空(表格形式的)
    数组
    关于meta元信息元素
    js判断数据类型
    Ising模型的Metropolis模拟中的组态阻塞和振荡
    python 画能级图
    python 调用 shell 命令,制作用户界面
    打包 python 程序,变成一个可执行文件
  • 原文地址:https://www.cnblogs.com/RobbinHan/p/2269588.html
Copyright © 2020-2023  润新知