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
- 开发者需要掌握的JS事件
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
- Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法
- 关于curl网站运维与开发的那些事
- 并查集Union-find及其在最小生成树中的应用
- go 语言的库文件放在哪里?如何通过nginx代理后还能正确获取远程地址
- 离线Tarjan算法-最近公共祖先问题
- Java文件上传下载实训
- 【网络编程系列】二:socket通信原理及实践
- textrank算法原理与提取关键词、自动提取摘要PYTHON
- 【网络编程系列】一:字节顺序的大端与小端表示法
- Linux下的make命令用法
- 增量数据丢失的原因分析(三)(r8笔记第91天)
- JS之浏览器对象BOM
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [全部章节]栈论 : 递归与栈式访问,如何用栈实现所有递归操作 (内附幼儿园题目,要笑着做完)
- Apache IoTDB 系列教程-2:基础 SQL 操作
- Apache IoTDB 系列教程-3:部署运维
- 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇)
- kali下安装beef并联合Metasploit
- 初次使用maven创建web工程发现只有一个idea目录,src,webapp目录都不见了,解决方案
- 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇,题目2)
- SQL注入原理及代码分析(一)
- SQL注入原理及代码分析(二)
- 写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出 现的次数。
- SSRF漏洞简单分析
- 树莓派基础实验30:BMP180气压传感器实验
- DC-1靶机实战和分析
- 如何用Python优雅的登录校园网?
- PHP入门之类型与运算符