好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

作者: Artech
出处: http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类:  [01] 技术剖析 ,  [02] 编程技巧

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于ASP.NET MVC的Razor引擎:IoC在View激活过程中的应用的详细内容...

  阅读:49次