ASP.NET MVC的Razor引擎:IoC在View激活过程中的应用

在《ASP.NET MVC的Razor引擎:RazorView》介绍BuildManagerCompiledView的时候,我们谈到默认使用的ViewPageActivator使用当前注册的DependencyResolver来完成对目标View的激活,这意味着我们可以通过注册自定义DependencyResolver的方式实现基于IoC的View激活。本篇文章中我们将演示如何通过自定义View的方式实现与IoC框架Ninject的集成。[本文已经同步到《How ASP.NET MVC Works?》中]

我们定义了一个具有如下定义的NinjectDependencyResolver,它具有一个IKernel类型的只读属性Kernel,该属性在构造函数中被初始化为一个StandardKernel对象。对于实现的GetService和GetServices方法,我们直接调用Kernel的TryGet和GetAll返回指定类型的实例和实例列表。为了方便进行类型映射,我们定义了泛型的Register<TFrom,TTo>方法。

   1: public class NinjectDependencyResolver : IDependencyResolver
   2: {
   3:     public IKernel Kernel { get; private set; }
   4:     public NinjectDependencyResolver()
   5:     {
   6:         this.Kernel = new StandardKernel();
   7:     }
   8:     public void Register<TFrom, TTo>() where TTo: TFrom
   9:     {
  10:         this.Kernel.Bind<TFrom>().To<TTo>();
  11:     }
  12:     public object GetService(Type serviceType)
  13:     {
  14:         return this.Kernel.TryGet(serviceType);
  15:     }
  16:     public IEnumerable<object> GetServices(Type serviceType)
  17:     {
  18:         return this.Kernel.GetAll(serviceType);
  19:     }
  20: }

我们演示的是一个针对多语言支持的场景,为了让View上输出的一些内容随着当前线程的UICulture而动态地变化,我们在一个ASP.NET MVC应用中定义如下一个读取资源内容抽象类ResourceReader。这里资源是一个宽泛的概念,并不对存储方式作强制的约束,我们可以使用资源文件也可以使用数据库来存储资源内容。简单起见,ResourceReader仅仅定义了一个唯一GetString方法获取指定名称的字符串。

   1: public abstract class ResourceReader
   2: {
   3:     public abstract string GetString(string name);
   4: }

我们默认采用资源文件来定义数据源,为此我们在项目中添加了两个资源文件Resoures.resx(语言文化中性)和Resources.zh.resx(中文),并在资源文件中添加了如下图所示的资源项(HelloWorld)。

然后我们创建如下一个默认的DefaultResourceReader,它默认读取我们添加的资源文件来获取GetString方法返回的字符串(静态类型Resources是添加资源文件自动创建的类型)。

   1: public class DefaultResourceReader : ResourceReader
   2: {
   3:     public override string GetString(string name)
   4:     {
   5:         return Resources.ResourceManager.GetString(name);
   6:     }
   7: }

为了让ResourceManager能够应用到所有的View中,我们为整个应用的View创建了如下一个基类LocalizableViewPage<TModel>。该类型是WebViewPage<TModel>的子类,它具有一个类型为ResourceManager的属性ResourceManager。由于该属性上应用了Ninject.InjectAttribute特性,意味着该属性会以“属性注入”的方式被自动初始化。

   1: public abstract class LocalizableViewPage<TModel>: WebViewPage<TModel>
   2: {
   3:     [Inject]
   4:     public ResourceReader ResourceReader { get;  set; }
   5: }

接下来我们定义了如下一个简单的HomeController,其默认的Action方法Index中直接将对应的View呈现出来。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7: }

如下所示的是Action方法Index对应View的定义,我们使用@inherits指令让动态编译生成的View类型继承自我们自定义的基类LocalizableViewPage<object>。我们直接调用ResourceReader属性的GetString方法提取名称为“HelloWorld”的字符串资源内容显示出来。

   1: @inherits LocalizableViewPage<object>
   2: <html>
   3:     <head>
   4:         <title></title>
   5:     </head>
   6:     <body>
   7:         <h2>@ResourceReader.GetString("HelloWorld")</h2>
   8:     </body>
   9: </html>

我们采用基于URL的语言文化决定机制,即将语言文化的代码置于请求URL中来决定希望采用的语言。为此我们在自动生成的RouteConfig类型中注册了如下一个URL模板为“{culture}/{controller}/{action}”的路由对象。

   1: public class RouteConfig
   2: {
   3:     public static void RegisterRoutes(RouteCollection routes)
   4:     {
   5:         //其他操作
   6:         routes.MapRoute(
   7:             name        : "Default",
   8:             url         : "{culture}/{controller}/{action}",
   9:             defaults    : new {
  10:             culture        = "zh-CN",
  11:             controller     = "Home",
  12:             action         = "Index"}
  13:         );
  14:     }
  15: }

我们自定义的DefaultResourceReader能够根据当前线程的UICulture选择对应的资源文件,那么我们只需要根据请求地址指示的语言文件对当前线程的语言文件进行相应的设置即可。于是我们在Global.asax定义了如下一个Application_BeginRequest方法使HttpApplication的BeginRequest事件触发的时候从请求地址中提取语言文化代码,然后对当前线程的语言文化进行相应的设置。除此之外,针对NinjectDependencyResolver的注册和ResourceReader与Default ResourceReader之间的映射关系定义在Application_Start方法中。

   1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         //其他操作
   6:         NinjectDependencyResolver dependencyResovler = new NinjectDependencyResolver();
   7:         dependencyResovler.Register<ResourceReader, DefaultResourceReader>();
   8:         DependencyResolver.SetResolver(dependencyResovler);
   9:     }
  10:  
  11:     protected void Application_BeginRequest()
  12:     { 
  13:         HttpContextBase contextWrapper = new HttpContextWrapper(HttpContext.Current);
  14:         string culture = RouteTable.Routes.GetRouteData(contextWrapper).Values["culture"] as string;
  15:         if (!string.IsNullOrEmpty(culture))
  16:         {
  17:             try
  18:             {
  19:                 CultureInfo cultureInfo                 = new CultureInfo(culture);
  20:                 Thread.CurrentThread.CurrentCulture     = cultureInfo;
  21:                 Thread.CurrentThread.CurrentUICulture   = cultureInfo;
  22:             }
  23:             catch {}
  24:         }
  25:     }
  26: }

现在运行我们的程序,并通过地址指定采用的语言文化,我们可以发现呈选出来的内容与你指定的语言文化是一致的,具体的输出效果如下图所示。

ASP.NET MVC的Razor引擎:View编译原理 ASP.NET MVC的Razor引擎:RazorView ASP.NET MVC的Razor引擎:IoC在View激活过程中的应用 ASP.NET MVC的Razor引擎:RazorViewEngine

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏walterlv - 吕毅的博客

都是用 DllImport?有没有考虑过自己写一个 extern 方法?

发布于 2018-09-06 13:58 更新于 2018-09...

7020
来自专栏me的随笔

ASP.NET Core Middleware

中间件(Middleware)是ASP.NET Core中的一个重要特性。**所谓中间件就是嵌入到应用管道中用于处理请求和响应的一段代码**。ASP.NET C...

14230
来自专栏Linux驱动

20.Linux-USB鼠标驱动

在上一章分析完USB总线驱动程序后, 接下来开始写一个USB驱动: 本节目的: 将USB鼠标的左键当作L按键,将USB鼠标的右键当作S按键,中键当作回车按键 参...

41380
来自专栏猿学

猿学-讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute

ASP.NET Core MVC 2.1 特意为构建 HTTP API 提供了一些小特性,今天主角就是 ApiControllerAttribute. (注:文...

7900
来自专栏MasiMaro 的技术博文

windows 多任务与进程

多任务的本质就是并行计算,它能够利用至少2处理器相互协调,同时计算同一个任务的不同部分,从而提高求解速度,或者求解单机无法求解的大规模问题。以前的分布式计算正是...

12840
来自专栏大内老A

ASP.NET Core的路由[3]:Router的创建者——RouteBuilder

在《注册URL模式与HttpHandler的映射关系》演示的实例中,我们总是利用一个RouteBuilder对象来为RouterMiddleware中间件创建所...

44240
来自专栏圣杰的专栏

ABP入门系列(11)——编写单元测试

源码路径:Github-LearningMpaAbp 1. 前言 In computer programming, unit testing is a soft...

32080
来自专栏me的随笔

ASP.NET Core Middleware

中间件(Middleware)是ASP.NET Core中的一个重要特性。所谓中间件就是嵌入到应用管道中用于处理请求和响应的一段代码。ASP.NET Core ...

15540
来自专栏hbbliyong

LINQ 图解 LINQ学习第三篇

LINQ,语言集成查询(Language INtegrated Query)是一组用于c#和Visual Basic语言的扩展。它允许编写C#或者Visual ...

31160
来自专栏恰童鞋骚年

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

  在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor。在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVeloc...

13530

扫码关注云+社区

领取腾讯云代金券