使用 Roslyn引擎动态编译代码
Roslyn引擎自2014年开源至今这么久,一直没怎么了解过,虽然VS2015早就集成了它。
以前老一套的动态编译方法在 .NET Core中似乎不再支持了,很多方法都是未实现的。下面就介绍如何在.NET Core环境中使用Roslyn进行动态编译。话不多说,Talk is cheap, show me the code.
首先是安装nuget包
Install-Package Microsoft.CodeAnalysis.CSharp
接下来是我们需要动态编译和执行的代码:
// 表达式树
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
using System; namespace RoslynCompileSample
{
public class Writer
{
public void Write(string message)
{
Console.WriteLine(message);
}
}
}");
紧接着是创建编译对象:
// 随机程序集名称
string assemblyName = Path.GetRandomFileName(); // 元数据引用
MetadataReference[] references = new MetadataReference[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
}; // 创建编译对象
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
然后是编译:
using (var ms = new MemoryStream())
{
// 将编译后的IL代码放入内存中
EmitResult result = compilation.Emit(ms); // 编译失败,提示
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
}
else
{
// 编译成功则从内存中加载程序集
ms.Seek(, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(ms.ToArray());
}
}
最后则是调用:
// 反射获取程序集中 的类
Type type = assembly.GetType("RoslynCompileSample.Writer"); // 创建该类的实例
object obj = Activator.CreateInstance(type); // 通过反射方式调用类中的方法。(Hello World 便是我们传入方法的参数)
type.InvokeMember("Write",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
obj,
new object[] { "Hello World" });
最后咱们可以封装一个方法,以便于调用:
/// <summary>
/// 动态编译
/// </summary>
/// <param name="code">需要动态编译的代码</param>
/// <returns>动态生成的程序集</returns>
public static Assembly GenerateAssemblyFromCode(string code)
{
Assembly assembly = null;
// 丛代码中转换表达式树
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
// 随机程序集名称
string assemblyName = Path.GetRandomFileName();
// 引用
var references = AppDomain.CurrentDomain.GetAssemblies().Select(x => MetadataReference.CreateFromFile(x.Location)); // 创建编译对象
CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream())
{
// 将编译好的IL代码放入内存流
EmitResult result = compilation.Emit(ms); // 编译失败,提示
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
}
else
{
// 编译成功,从内存中加载编译好的程序集
ms.Seek(, SeekOrigin.Begin);
assembly = Assembly.Load(ms.ToArray());
}
}
return assembly;
}
使用 Roslyn引擎动态编译代码的更多相关文章
- 基于 Roslyn 实现动态编译
基于 Roslyn 实现动态编译 Intro 之前做的一个数据库小工具可以支持根据 Model 代码文件生成创建表的 sql 语句,原来是基于 CodeDom 实现的,最近改成使用基于 Roslyn ...
- 基于roslyn的动态编译库Natasha
人老了,玩不转博客园的编辑器,详细信息转到:https://mp.weixin.qq.com/s/1r6YKBkyovQSMUgfm_VxBg 关键字:Github, NCC, Natasha,Ros ...
- C#动态编译代码,执行一个代码片段,或者从指定文件中加载某个接口的实现类
在项目进行中有时候会需要配置一些复杂的表达式,在程序运行的时候执行表达式,根据结果执行相应的操作,简单写了一个类Expression,利用.net的动态编译技术实现,代码如下: public clas ...
- 用eval 动态编译代码
eval 有另外一种用法, 其参数是作为一个字串表达式, 而不是代码块.在运行时, 它将字串临时编译成代码并且执行. 这很易用, 但也很危险, 因为有可能会把具有危害性的代码放到字串里. foreac ...
- C#实现动态编译代码
/*------------------------------------------------------------------------------ * Copyright (C) 201 ...
- ZKWeb网站框架的动态编译的实现原理
ZKWeb网站框架是一个自主开发的网页框架,实现了动态插件和自动编译功能. ZKWeb把一个文件夹当成是一个插件,无需使用csproj或xproj等形式的项目文件管理,并且支持修改插件代码后自动重新编 ...
- 让C#语言充当自身脚本!——.NET中的动态编译
原文:让C#语言充当自身脚本!--.NET中的动态编译 代码的动态编译并执行是.NET平台提供给我们的很强大的一个工具,用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码 ...
- 分享基于.NET动态编译&Newtonsoft.Json封装实现JSON转换器(JsonConverter)原理及JSON操作技巧
看文章标题就知道,本文的主题就是关于JSON,JSON转换器(JsonConverter)具有将C#定义的类源代码直接转换成对应的JSON字符串,以及将JSON字符串转换成对应的C#定义的类源代码,而 ...
- .Net 动态编译(c# 脚本)
1 用.NET提供的类动态编译代码字符串,生成DLL存于内存中,加载到程序域 2 用反射的方式调用这个DLL 将要被编译和执行的代码读入并以字符串方式保存声明CSharpCodeProvider对象实 ...
随机推荐
- Windows下的Jdk 1.7*安装并配置(图文详解)
不多说,直接上干货! 很多人很少去想,为什么在windows下,安装完Jdk的安装包之后,还需要去配置环境变量,只是知道要这么去做,没有想过为什么要去这么做? 答:由于java是平台无关的 ,安装jd ...
- CCF 201509-3 模版生成系统
试题编号: 201509-3 试题名称: 模板生成系统 时间限制: 1.0s 内存限制: 256.0MB 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的 ...
- scala-04-set操作
Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的. Scala 集合分为可变的和不可变的集合. 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scal ...
- map集合的见解、排序
map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等 HashMap:我们最常用的Map,它根据key的HashCode 值 ...
- sql的存储过程实例--循环动态创建表
创建一个存储过程,动态添加100张track表表名track_0 ~~ track_99注:sql的拼接只能用 CONCAT()函数 -- 创建一个存储过程 CREATE PROCEDURE crea ...
- CentOS6.5 QT5.3 找不到GLIBCXX3.4.15解决方法
下载安装后 启动的时候提示 GLIBCXX_3.4.15,发现libstdc++.so.6的版本过, 在安装qt-creator的时候运行这个IDE就出现了这个问题,是由于libstdc++.so.6 ...
- Python模块:日志输出—logging模块
1. logging介绍 Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用.这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/ ...
- ActiveMQ P2P版的HelloWorld
1.2 JMS应用程序接口 ConnectionFactory: 用户用来创建到JMS提供者的连接的被管对象.JMS客户通过可移植的接口访问连接,这样当下层的实现改变时,代码不需要进行修改. 管理员 ...
- NYOJ 1013 除法表达式(欧几里德算法+唯一分解定理)
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1013 描述 给出一个这样的除法表达式:X1/X2/X3/···/Xk,其中Xi是 ...
- tomcat 防火墙如何设置
tomcat 防火墙能够有效的防护我们电脑,那么我们要怎么样去设置呢?下面由学习啦小编给你做出详细的tomcat 防火墙设置方法介绍!希望对你有帮助! tomcat 防火墙设置方法一: 1.为tomc ...