热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用Razor在ASP.NETMVC中的实现,自定义视图引擎框架(2)

ASP.NETMVC3开始使用Razor作为其视图引擎,取代了原来ASP.NETWebForm引擎。笔者最近研究了一下MVC3对Razor的实现,从中找

ASP.NET MVC3开始使用Razor作为其视图引擎,取代了原来ASP.NET Web Form引擎。笔者最近研究了一下MVC3对Razor的实现,从中找到一个切入点,能够让我们自定义基于Razor语法的视图解析引擎。在项目里面可以用于诸如邮件模板定制等方面。目前,只是一个demo版本,还在进一步完善中。CodePlex : http://codeof.codeplex.com/SourceControl/list/changesets 其中的RazorEx

目前支持的功能:

1.支持Razor语法(基本的@语法)的模板文件解析
2.支持Layout / Renderbody语法
3.支持类似asp.net 动态编译机制,在程序运行期间,如果模板文件变了,无需重新编译
4.支持名字空间引用配置
5.支持复杂的程序集引用关系

在利用Razor在ASP.NET MVC中的实现,自定义视图引擎框架(1)中,介绍了如何利用微软实现的System.Web.Razor来解析基于Razor语法的模板,最后得到一个编译单元或者源码。本文介绍如何在代码中对编译单元或者源码进行动态编译,并执行。

应该没有比动态编译更灵活的了,它允许我们动态的创建程序代码并编译执行。尽管它灵活,但是实现复杂,并且效率不高,不到万不得已不要考虑。而在这个case中却不得不用这种方式,因为模板是用户创建的,我们永远不可能预知:

image

在.net中,System.CodeDom.Compiler.CodeDomProvider提供了将一个或多个源程序或编译单元编译成程序集的方法。在.net4.0中Microsoft.CSharp.CSharpCodeProvider继承了上面这个类,并给予了实现。有了CSharpCodeProvider,编译一个动态的程序集十分容易:

CSharpCodeProvider provider = new CSharpCodeProvider();CompilerParameters c_options = new CompilerParameters();c_options.IncludeDebugInformation = false;c_options.GenerateExecutable = false;c_options.GenerateInMemory = true;c_options.ReferencedAssemblies.Add( "System.dll" );CompilerResults results = provider.CompileAssemblyFromSource(c_options, code);

上面的代码段,实例化了一个CSharpCodeProvider以及一个CompilerParameters。前者用于编译,后者用于指定编译时的一些选项,如上面的代码的设置。最后调用CompileAssemblyFromSource,传入编译选项和源代码文本即可。另外CSharpCodeProviderCompileAssemblyFromDom重载,可以接受编译选项对象和

CodeCompileUnit对象作为参数。在上一篇中,我们知道RazorTemplateEngine.GenerateCode方法返回的刚好是包含了CodeCompileUnit的对象,所以我们将使用CompileAssemblyFromDom方法

在返回值CompilerResults.CompiledAssembly中,我们可以访问到编译结果的Assembly对象,再结合反射即可执行编译代码。另外,在编译过程中,如果编译失败将抛出异常。

在引擎的开发过程中,除了上一篇和上述需要知道的基本内容外,分别有以下问题需要解决:

1、动态编译时需要知道引用哪些dll,否则将无法编译成功。比如在模板里面我引用了一个复杂对象,这个对象定义显然不在引擎的程序集中,可能是用户自己的程序集,或是用户程序集引用的程序集。这就带来了一个问题,在编译时我们如何知道要引用哪些程序集?我用了一个比较笨的方案:从GetCallingAssembly开始,把相互依赖的程序集遍历一遍,并且全部在编译时引用。代码中的AssemblyReferenceResolver就实现了这个功能;

2、如上面的问题,编译的时候,源码需要有正确的命名空间的引用,否则即使引用的程序集,还是不能编译成功。为此,模仿mvc的实现,设计了一个configuration,添加下面这样的配置文件即可:


3、一个模板对应一个类,也就对应一个程序集,如果反复解析模板会反复编译,这样会很大程度上影响效率。解决方案是使用缓存:将编译过的dll和模板文件存成字典,如果已经编译过了并且模板文件的最后更新时间不晚于dll的创建时间,则直接返回之前编译的程序集;否则就进行编译。代码中的DynamicAssemblyCache类就实现这个功能;

4、如何实现模板嵌套。在基类__TemplatePage中加入下面属性和方法:

private string _layout;public virtual string Layout {get { return _layout; }set {_layout = value;}}public string ChildBody { get; set; }public virtual string RenderBody(){if(ChildBody != null)return ChildBody;return string.Empty;}

这样类似Layout=””  @RenderBody的语法就可以通过编译。配合递归的Execute即可实现。

 

 

项目现已实现基本的功能,我打算过一段试用期过后Release一个版本。源码在上面的CodePlex上,代码不多,还有待重构,有兴趣的同仁可以和我讨论,希望能实现一个健壮的引擎。

转:https://www.cnblogs.com/P_Chou/archive/2011/08/30/customize-razor-template-2.html



推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • position属性absolute与relative的区别和用法详解
    本文详细解读了CSS中的position属性absolute和relative的区别和用法。通过解释绝对定位和相对定位的含义,以及配合TOP、RIGHT、BOTTOM、LEFT进行定位的方式,说明了它们的特性和能够实现的效果。同时指出了在网页居中时使用Absolute可能会出错的原因,即以浏览器左上角为原始点进行定位,不会随着分辨率的变化而变化位置。最后总结了一些使用这两个属性的技巧。 ... [详细]
  • React基础篇一 - JSX语法扩展与使用
    本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 本文介绍了2015年九月八日的js学习总结及相关知识点,包括参考书《javaScript Dom编程的艺术》、js简史、Dom、DHTML、解释型程序设计和编译型程序设计等内容。同时还提到了最佳实践是将标签放到HTML文档的最后,并且对语句和注释的使用进行了说明。 ... [详细]
  • 第8章 使用外部和内部链接
    8.1使用web地址LearnAboutafricanelephants. ... [详细]
  • 今天就跟大家聊聊有关怎么在Android应用中实现一个换肤功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根 ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
author-avatar
梦晗明镜百_576
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有