什么是Roslyn

从C# 6 开始,编译器被完全用C#重写并且模块化,这个模块化的编译器就是Roslyn。利用Roslyn,我们可以方便地在我们的程序中动态编译代码,即,把代码当做数据传递给Roslyn编译器,得到编译后的程序集。

安装并引用Roslyn

在开始使用之前,先在使用Nuget安装Microsoft.CodeAnalysis.CSharp
之后在命名空间声明中,添加

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;

编译流程

在使用Roslyn之前,对编译器如何把源代码翻译成MSIL的过程,即,编译流程有个大概了解,对我们得心应手使用这个工具非常有帮助。

源文件读取

编译的第一步是读取源文件,在Roslyn里面用SourceText表示源文件**,支持多种不同的源文件读取,包括从文件流读取、直接在源代码指定literal的方式,像以下两种方式常用

         SourceText st; //从文件流读取using (var fs = new FileStream(filePath, FileMode.Open)){st = SourceText.From(fs);}st = SourceText.From(@"public class TestClass {}"); //直接用literal方式指定源代码

语法树解析

读取源文件之后,我们需要根据源文件解析生成语法树。在Roslyn里面用SyntaxTree表达语法树。Roslyn在这一步中将会检查语法的合理性,如果有语法错误,可以通过调用SyntaxTree的方法GetDiagnostics查看。在生成语法树的时候,可以通过传入的ParseOption控制编译语言版本设定、预处理变量设定,等。

st = SourceText.From(@"public class TestRoslyn { public void Test(){ Console.FakeMethod(); } }"); //没有引用Console,同时Console里面没有FakeMethod这个方法,但是语法解析不会报错,只要语法是正确的就没问题。CSharpParseOptions option = new CSharpParseOptions(LanguageVersion.CSharp8, preprocessorSymbols: new List<string>() { "Debug"}); //确定使用C# 的版本和传入的预编译量
var tree = CSharpSyntaxTree.ParseText(st, option);
Debug.Assert(tree.GetDiagnostics().ToList().Count == 0);

语义解析

语法解析确保了我们的源代码符合C#的语法,比如,有相对应的{},每个字句后面有;,等。但是语法正确只是第一步,我们需要进一步确保我们每条调用语句都是正确的,即,我们引用的类,已经正确的引用到了我们的编译中并且声明在命名空间引用中,同时我们每个语句调用必须调用在正确的函数上,必须传递正确的参数。要做到这一步,我们需要的是语义解析。
 
在Roslyn使用CSharpCompilation完成语义解析,这是一个静态类,在创建的时候我们可以传入的参数有很多,但最主要的就是,想要创建的模块名称、参与语义解析的语法树(可以有多个语法树,代表可以编入同一个模块的不同文件)、引用的程序集(mscorlib.dll是必须的)和目标类型(dll或者exe)。

var compileOption = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create(
"class1",
new List<SyntaxTree> { tree }, //这是前面生成的语法树
new List<MetadataReference>() { MetadataReference.CreateFromFile(typeof(int).Assembly.Location) }, //这是一个得到msconlib的好办法
compileOption);
Debug.Assert(tree.GetDiagnostics().ToList().Count == 0); //如果之前有引用缺失、调用方法错误,这里就会体现出来

生成IL代码到程序集文件

最后我们把代码发射到程序集文件(可以是exe也可以是dll),同时可以生成pdb文件。

var assemblyPath = @"D:\Roslyn\class1.dll";
var pdbPath = @"D:\Roslyn\class1.pdb";
var result = compilation.Emit(assemblyPath, pdbPath); //result表明了执行是否成功

至此,一个动态编译代码生成程序集的流程就完成了。

用途

生成了dll之后,我们可以通过反射加载,或者直接在工程文件中引用的方式使用。
我们一般在构建脚本系统的时候会较多的使用动态代码编译的方法,通过监听脚本源文件,动态的生成程序集,给脚本系统添加不同的功能。
希望对大家能有点帮助。

使用Roslyn动态编译代码相关推荐

  1. 使用Roslyn动态编译和执行

    1. 安装nuget package 2.使用Roslyn 动态执行 var engine = new Roslyn.Scripting.CSharp.ScriptEngine();engine.Cr ...

  2. python 动态编译代码_使用PyQt(Python+Qt)+动态编译36行代码实现的计算器

    PyQt是基于跨平台的图形界面C++开发工具Qt加Python包装的一个GPL软件(GPL是GNU General Public License的缩写,是GNU通用公共授权非正式的中文翻译),Qt基于 ...

  3. python 动态编译代码_编译Python代码以使用Cython静态链接可执行文...

    经验丰富的问题??显然来自链接器(gcc在引擎盖下启动了一个链接器,看到它 – 只需用详细模式启动带有-v的gcc).那么让我们先简要提醒链接过程如何工作: 链接器保留其需要解析的所有符号的名称.在开 ...

  4. C#实现动态编译代码

    /*------------------------------------------------------------------------------* Copyright (C) 2013 ...

  5. python 动态编译代码,Python:在运行时动态创建函数

    How to dynamically create a function in Python? I saw a few answers here but I couldn't find one whi ...

  6. NetCore基于Roslyn的动态编译实现

    目录 一. AvalonEdit文本器 1.功能实现 2. 高亮 3. 代码提示 4. 动态编译 1)依赖项初始化 2) 编译函数 二. 运行效果展示 三. 源码链接 四. 参考资料 一. Avalo ...

  7. 基于roslyn的动态编译库Natasha

    人老了,玩不转博客园的编辑器,详细信息转到:https://mp.weixin.qq.com/s/1r6YKBkyovQSMUgfm_VxBg 关键字:Github, NCC, Natasha,Ros ...

  8. 基于 Roslyn 实现动态编译

    基于 Roslyn 实现动态编译 Intro 之前做的一个数据库小工具可以支持根据 Model 代码文件生成创建表的 sql 语句,原来是基于 CodeDom 实现的,最近改成使用基于 Roslyn ...

  9. eclipse编译java项目class文件_动态编译 Java 代码以及生成 Jar 文件

    导读: 最近在看 Flink 源码的时候发现到一段实用的代码,该代码实现了 java 动态编译以及生成 jar 文件.将其进行改进后可以应用到我们的平台上,实现在平台页面上编写 java 代码语句,提 ...

  10. Java脚本引擎执行js代码以及动态编译

    Java脚本引擎执行js代码 一.概述 JAVA脚本引擎是从JDK6.0之后添加的新功能. 使得 Java 应用程序可以通过一套固定的接口与各种脚本引擎交互,从 而达到在 Java 平台上调用各种脚本 ...

最新文章

  1. web客户端 http error 413
  2. 【 MATLAB 】通过不同样本数的同一个有限长序列作 DTFT 对比
  3. 【深入Java虚拟机JVM 03】Java内存模型
  4. 实验1 熟悉实验环境
  5. 数据统计告诉你,程序员是不是35岁就退休
  6. oracle apex 日志,oracle-apex - 在oracle apex报告中显示员工记录或经理记录及其员工 - SO中文参考 - www.soinside.com...
  7. 安卓 qemu 运行linux,在Qemu的beagleboard上运行Android
  8. 网易云音乐ncm文件格式转mp3格式教程
  9. java解四元一次方程
  10. 全方面对比流行报表开发工具,哪一个才是你的菜?
  11. 2020牛客暑期多校训练营(第九场)I .The Crime-solving Plan of Groundhog
  12. qq邮箱收信服务器imap,普通IMAP、POP邮箱的设置 教你使用iPhone邮件客户端管理QQ邮箱...
  13. Google VR 学习小结
  14. outlook从服务器中恢复已删除项目,恢复邮箱中的已删除邮件:Exchange 2013 帮助 | Microsoft Docs...
  15. 在Java中计算一元线性回归
  16. html5新特性(一)
  17. 第一章 略说中医的学习与研究(4)
  18. 如何实现从CTO到CEO的跨越(红色标注是我关注的点)
  19. java程序框图 质数_判断质数的程序框图和算法
  20. 【webrtc】fdk-aac 编解码库cmake和 gn编译

热门文章

  1. 联想K31笔记本完全拆解,装不回去了。想做个电视机或者显示器
  2. MATLAB系统辨识工具箱学习,详细教程!
  3. ui设计app设计风格有哪些?ui设计app界面设计流程是什么?
  4. 计算机网络被限速,电脑网速被限制怎么办
  5. 办公软件是计算机吗,什么是办公软件_IT /计算机_资料
  6. ORA-12162: TNS:net service name is incorrectly specified 错误解决
  7. EJB是什么,以及weblogic和tomcat的区别
  8. C库-atoi(), atol(), atoll(), atof(), ceil(), ceilf(), ceill()
  9. C#+ AE实现地图注记功能
  10. 计算机应用基础 (2013),计算机应用基础