博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC的Razor引擎:IoC在View激活过程中的应用
阅读量:6692 次
发布时间:2019-06-25

本文共 4826 字,大约阅读时间需要 16 分钟。

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

我们定义了一个具有如下定义的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
() where TTo: TFrom
9:     {
10:         this.Kernel.Bind
().To
();
11:     }
12:     public object GetService(Type serviceType)
13:     {
14:         return this.Kernel.TryGet(serviceType);
15:     }
16:     public IEnumerable 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
: WebViewPage
2: {
3:
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
2: 
3:     
4:         
5:     
6:     
7:         

@ResourceReader.GetString("HelloWorld")

8:     
9: 

我们采用基于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
();
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: }

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

作者:蒋金楠
微信公众账号:大内老A
微博:
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号
蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
你可能感兴趣的文章
腾讯云宣布核心产品全线降价,最高降幅达50%
查看>>
理解JavaScript中的this
查看>>
云帮一周问答集锦(10.31-11.06)
查看>>
mysql全文索引的原理
查看>>
Node.js + Redis Sorted Set 任务队列
查看>>
验证码破解技术四部曲之使用Tesseract(二)
查看>>
Retrofit2.0 公共参数(固定参数)
查看>>
webpack使用之基础篇
查看>>
如何避免if else
查看>>
android团队对新技术的态度
查看>>
『.NET Core CLI工具文档』(十)dotnet-build
查看>>
AngularJS中$q的promise使用及链式调用传值问题
查看>>
Scala Essentials: 类型约束
查看>>
JS异步那些事 二 (分布式事件)
查看>>
[分享]iOS开发-50行代码实现图文混排
查看>>
Ruby on Rails Ping ++ 支付
查看>>
[图像处理]ubuntu下Qt+Opencv配置过程
查看>>
Java 8:如何使用流方式查询数据库?
查看>>
如何修改 git 记录?
查看>>
技术团队代码管理和部署
查看>>