.NET Core中使用Razor模板引擎

一、简介

  在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作;在以前我们一般常用的有RazorNVeocityVTemplate。虽然所有的模板系统都具有一些共同特征,但 Razor却和我们前面讨论的二种视图引擎截然不同。不同于其它视图引擎,Razor在使用XML代 码方面没有走得那么极端。它也不完全类似于ASPX,因为它把那些比较笨重的占位符替换成@符号接表达式或者普通的控制块。因为不需要特殊的结束标记,所 以Razor最终的代码很简练。

  本篇介绍的主角是Razor,在非Core的版本中,我们常用开源的RazorEngine来解决我们的问题;但是它却没有对应.NET Core的版本。我们也只要自己动手来完成一个支持.NET Core的“模板引擎”版本。

  一般情况下使用Razor作为视图引擎要实现如下步骤:

  (1)读取模板文件 -> (2)生成Raozr的C#代码 -> (3)使用Roslyn编译代码生成程序集 -> (4)动态加载程序集 -> (5)反射调用

  

回到目录

二、非Mvc中使用Razor

  我们一般在使用Razor时都是在ASP.NET MVC中使用.cshtml来作为模板,由ASP.NET MVC的视图引擎(ViewEngine)来生成页面的代码的,总之,这里想说的是,模板引擎是独立的,它们甚至是独立的项目,由不同的公司和组织来开发。这次我们要在非Mvc中使用Raozr;首先我们要“脱离”Mvc的环境。

这里我们只在.NET Core程序中引用微软Raozr部分的程序集Microsoft.AspNetCore.Razor 1.0版本,这个程序集负责将模板生成出C#代码。

1.Project.json添加引用

        
  1. "dependencies": {

  2.    "Microsoft.AspNetCore.Razor": "1.0.0"

  3.    "NETStandard.Library": "1.6.0"

  4.   }

2.模板生成代码

  如下是摘录的YOYOFx框架中的一段代码,因为我们要生成代码时一般需要传入Model数据,这时需要Model Type组织代码时,要将泛型的情况考虑进去 。这里的RazorViewTemplate是一个模板基类,这里包含了模板中调用的外部方法,我们常用到的如HtmlHelper、Render、Url、Raw等方法或类都是通过这个柜顶模板定义的,RazorViewTemplate是一个自定义类不需要继承其它类型,如果想扩展模板中使用的方法,只需要在这个类中加入即可。

        
  1.    public class CodeGenerateService

  2.    {

  3.        public GeneratorResults Generate(Type modelType,string template)

  4.        {

  5.            //准备临时类名,读取模板文件和Razor代码生成器

  6.            string templateType = "YOYO.AspNetCore.ViewEngine.Razor.RazorViewTemplate";

  7.            string templateTypeName = modelType != null ? string.Format(templateType + @"<{0}>", modelType.FullName) : templateType;

  8.            var class_name = "c" + Guid.NewGuid().ToString("N");

  9.            var host = new RazorEngineHost(new CSharpRazorCodeLanguage(), () => new HtmlMarkupParser())

  10.            {

  11.                DefaultBaseClass = templateTypeName,

  12.                DefaultClassName = class_name,

  13.                DefaultNamespace = "YOYO.AspNetCore.ViewEngine.Razor",

  14.                GeneratedClassContext =

  15.                                   new GeneratedClassContext("Execute", "Write", "WriteLiteral", "WriteTo",

  16.                                                             "WriteLiteralTo",

  17.                                                             "RazorViewTemplate.Dynamic", new GeneratedTagHelperContext())

  18.            };

  19.            host.NamespaceImports.Add("System");

  20.            host.NamespaceImports.Add("System.Dynamic");

  21.            host.NamespaceImports.Add("System.Linq");

  22.            host.NamespaceImports.Add("System.Collections.Generic");

  23.            var engine = new RazorTemplateEngine(host);

  24.            return engine.GenerateCode(new StringReader(template));

  25.        }

  26.   }

  通过以上代码得到GeneratorResults类型的结果,从而可以得知生成过程是否成功,错误在位置等信息。最后通过GeneratedCode属性,得到生成好的C#代码。

    3.编译模板

  一般Razor的C#代码生成后,都是通过CodeDom来生成和编译代码的;.NET开源后,我们又多了一个强大的选择Roslyn , Roslyn也是支持.NET Core的,并且在整个.NET平台中,扮演着非常重要的角色,小到这种视图代码编译,大到整个项目的编译场景都有Roslyn的身影。微软最新开源的Visual Studio Code中C#插件,OmniSharp就是通过Roslyn来对项目和编辑器提供支持的。

  摘录YOYOFx代码如下:

        
  1. public Type Compile(string compilationContent)

  2. {

  3.     var assemblyName = Path.GetRandomFileName();

  4.     var sourceText = SourceText.From(compilationContent, Encoding.UTF8);

  5.     var syntaxTree = CSharpSyntaxTree.ParseText( sourceText, path: assemblyName, options: new CSharpParseOptions());

  6.     var compilation = CSharpCompilation.Create(assemblyName, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),                  

  7.                      

  8.   syntaxTrees: new[] { syntaxTree },

  9.                        references: ApplicationReferences );

  10.     using (var assemblyStream = new MemoryStream())
       {

  11.         var result = compilation.Emit(assemblyStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb));

  12.         this.CompileResult = new CompileResult(){ Success = result.Success, Errors = result.Diagnostics.Select(d => d.ToString()).ToList()};

  13.         if (!result.Success){

  14.             if (!compilation.References.Any() && !ApplicationReferences.Any())

  15.                 throw new InvalidOperationException("project.json preserveCompilationContext");

  16.             return null;

  17.         }

  18.         var templateType = LoadTypeForAssemblyStream(assemblyStream, null);

  19.         return templateType;

  20.     }

  21. }

   在代码中可以通过CompileResult得到相应的编译错误信息,同样包括错误的信息和具体错误所在的行。

  其中注意的是LoadTypeForAssemblyStream方法,因为在.NET Core中动态加载程序集的方式跟以前有所不同AppDomain的概念现在已经消失,所以要在.NET Core动态加载程序集要使用,命名空间System.Runtime.Loader中的AssemblyLoadContext.Default.LoadFromStream 方法,而在.NET 4.5+中要使用Assembly.Load方法。


 三、总结

   Razor 不仅仅使用了动态的编译,还有一个强大的模板解析的功能。利用自定义的模板基类还可以在模板里提供一些辅助方法。这样看来 Razor 也算是 C# DSL 的一种实现了。

原文地址:http://www.cnblogs.com/maxzhang1985/p/5939286.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea中Gitlab项目导入导出

idea中Gitlab项目导入导出 2018年04月16日 16:39:23 蓝之刃 阅读数&#xff1a;15415 Gitlab的使用 Gitlab跟Github类似&#xff0c;都是代码托管的网站&#xff0c;最大的不同是Gitlab创建的项目可以免费私有的&#xff0c;不必像Github那样收费&#xff0c;而且Gitlab还可…

服务器 ha linux,Linux 高可用(HA)集群之Heartbeat详解

大纲一、Heartbeat 的定义二、Heartbeat 的版本与组件三、Heartbeat 的各版本之间的区别四、Heartbeat 集群的一般拓扑图推荐阅读&#xff1a;一、Heartbeat的定义Heartbeat 项目是 Linux-HA 工程的一个组成部分&#xff0c;也是目前开源HA项目中最成功的一个例子&#xff0c;L…

一篇文章彻底了解清楚什么是负载均衡

转载自 一篇文章彻底了解清楚什么是负载均衡 负载均衡是高可用网络基础架构的的一个关键组成部分&#xff0c;有了负载均衡&#xff0c;我们通常可以将我们的应用服务器部署多台&#xff0c;然后通过负载均衡将用户的请求分发到不同的服务器用来提高网站、应用、数据库或其他…

intellij-IDE运行Java程序报错:java: -source 1.5 中不支持 lambda 表达式 有用

intellij-IDE运行Java程序报错&#xff1a;java: -source 1.5 中不支持 lambda 表达式 2017年12月29日 15:04:15 佛空如水 阅读数&#xff1a;795 报错&#xff1a; 解决&#xff1a; 第一步修改&#xff1a; 第二步修改&#xff1a;

linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

摘要&#xff1a;媒介 Device Tree是一种用去描绘硬件的数据布局&#xff0c;类似板级描绘说话&#xff0c;发源于OpenFirmware(OF)。正在现在遍及应用的kernel 2.6.x版本中&#xff0c;对分歧仄台、分歧硬件&#xff0c;往]前言Device Tree是一种用来描述硬件的数据结构&#…

gRPC .NET Core跨平台学习

前些天发布gRPC C# 学习&#xff0c;在.NET Framework 中使用gRPC &#xff0c;今天来学习 .NET Core gRPC。 gRPC 的.NET Core 包在NuGet 上发布了&#xff0c;结合.NET Core 实现gRPC 完美跨平台。 本篇主要讲解 .NET Core 版gRPC客户端运行在Ubuntu系统上&#xff0c;与局域…

IDEA导入Maven项目,pom.xml文件中 有inspects a maven model for resolution problems报错 !!!!!!!!!!有用

IDEA导入Maven项目&#xff0c;pom.xml文件中 有inspects a maven model for resolution problems报错 2018年08月06日 22:13:09 东方不能败 阅读数&#xff1a;4616 我是导入一个已经写好的Maven工程&#xff0c;导入后返现在pom.xml文件中有inspects a maven model for res…

Windows Server 2016提供Docker原生运行的企业级支持

Windows Server 2016已原生支持Docker&#xff0c;这使得Windows应用可运行在容器中。该评估版目前已经可用&#xff0c;期望于本月底之前&#xff0c;Microsoft将提供从评估版到RTM的升级路径。该评估版发布于上周的Microsoft Ignite大会上&#xff0c;同时还发布了Microsoft和…

arm linux串口控制led,通信程序设计 - Linux下ARM和单片机的串口通信设计

3 通信程序设计ARM 与单片机的串口通信程序包括两方面&#xff1a; 一方面是作为上位机的ARM 的串口通信程序&#xff0c;另一方面是作为下位机的单片机的串口通信程序。在通信之前必须制定合理的通信协议以保证通信的可靠性和成功率。现约定双方通信协议如下&#xff1a;( 1) …

为什么我强烈建议大家使用枚举来实现单例

转载自 为什么我墙裂建议大家使用枚举来实现单例 关于单例模式&#xff0c;我的博客中有很多文章介绍过。作为23种设计模式中最为常用的设计模式&#xff0c;单例模式并没有想象的那么简单。因为在设计单例的时候要考虑很多问题&#xff0c;比如线程安全问题、序列化对单例的…

idea @Data 不起作用找不到 相关的注解

idea中Data标签getset不起作用(这个有用&#xff0c;下面的没用) 2017年06月08日 11:22:40 seapeak007 阅读数&#xff1a;25816 spring cloud中使用Data标签&#xff0c;不用手动添加get set方法&#xff0c;但是如果项目中其他类中使用getset方法&#xff0c;如果报错&…

搭建分布式 ASP.NET Core Web

单台Web处理用户请求的能力是有限的&#xff0c;因此我们可能会需要搭建分布式的Web服务器。 当前市面上&#xff0c;可能用的比较多的是会话保持&#xff0c;这种模式下&#xff0c;开发者只需将先前开发好的、不支持会话共享的程序部署在多台服务器上&#xff0c;负载均衡提供…

五分钟了解CDN

转载自 五分钟了解CDN一、什么是CDN&#xff1f; CDN全称Content Delivery Network&#xff0c;即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输的更快、更稳定。 通过在网络各处放置节点服务器所构成的在现…

Eclipse导入他人的Maven工程报错

一.什么是maven? Maven是一个项目管理工具&#xff0c;它包含了一个项目对象模型 (Project Object Model)&#xff0c;一组标准集合&#xff0c;一个项目生命周期(Project Lifecycle)&#xff0c;一个依赖管理系统(Dependency Management System)&#xff0c;和用来运行定义在…

拼图游戏C语言课设实验报告,C语言拼图游戏实验报告.doc

C语言拼图游戏实验报告课程设计实验报告班级&#xff1a;光电104—2 姓名&#xff1a;刘云龙 学号&#xff1a;201058501220一、实验题目&#xff1a;使用C语言编写一个小游戏(拼图游戏)二、实验目的&#xff1a;C语言是每一个通信学生的必修课之一&#xff0c;此次课程设计要求…

.Net开源微型ORM框架测评

什么是ORM? 对象关系映射&#xff08;英语&#xff1a;Object Relation Mapping&#xff0c;简称ORM&#xff0c;或O/RM&#xff0c;或O/R mapping&#xff09;&#xff0c;是一种程序技术&#xff0c;用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说&am…

大家都在说的分布式系统到底是什么

转载自 大家都在说的分布式系统到底是什么随着大型网站的各种高并发访问、海量数据处理等场景越来越多&#xff0c;如何实现网站的高可用、易伸缩、可扩展、安全等目标就显得越来越重要。为了解决这样一系列问题&#xff0c;大型网站的架构也在不断发展。提高大型网站的高可用架…

2015c语言9月答案,2015年9月计算机二级C语言预测题答案

2015年9月计算机二级C语言预测题答案一、 选择题1、B 2、C 3、D 4、C 5、C 6、D 7、C 8、D 9、C 10、D11、D 12、D 13、B 14、B 15、A 16、D 17、B 18、B 19、C 20、D二、 阅读程序题(1) 6&#xff0c;8 (2) 3.141593,3.1416,3.142 (3) 4 (4) 2&#xff0c;4 (5) 8三、 程序填空…

Redis集群~StackExchange.Redis(10月6号版1.1.608.0)连接Twemproxy支持Auth指令了

对于StackExchange.Redis这个驱动来说&#xff0c;之前的版本在使用Proxy为Twemproxy代理时&#xff0c;它是不支持Password属性的&#xff0c;即不支持原始的Auth指令&#xff0c;而我也修改过源代码&#xff0c;为CommandMap添加了Auth但最后测试的结果还是失败了&#xff0c…

使用JDOM2.0.4 操作/解析xml

转载自 使用JDOM2.0.4 操作/解析xml一、解析xml内容 xml文件内容:<?xml version"1.0" encoding"utf-8"?> <RETVAL successtrue> <Shop><sid>1</sid><name>北京鑫和易通贸易有限公司</name></Shop> &l…