使用 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对象实 ...
随机推荐
- [转]Android中handler机制的原理
Andriod提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange). 1)Loo ...
- eclipse maven jdk全局设置
<profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</acti ...
- HTTP笔记(二)
HTTP首部 不管是请求报文还是响应报文,都会包含首部信息.HTTP首部都是由字段名和字段值构成的,中间由英文冒号:隔开.一个首部字段名可以对应多个字段值. 四种首部字段的类型: 通用首部字段:请求报 ...
- Spring mvc 4系列教程(一)
一.Spring框架概览 Spring框架是一种轻量级.一站式解决企业级应用的解决方案.不仅如此,Spring的模块化的特点,可以使你只引用所需要的部分,而无需引用全部.你可以使用控制反转容器(IoC ...
- 第一次项目上Linux服务器(四:CentOS6下Mysql数据库的安装与配置(转))
一.mysql简介 说到数据库,我们大多想到的是关系型数据库,比如mysql.oracle.sqlserver等等,这些数据库软件在windows上安装都非常的方便,在Linux上如果要安装数据库,咱 ...
- Java @Repeatable
查看@PropertySource注解时候,发现了@Repeatable,从来没见过的注解,学习了下: 首先介绍下@Repeatable注解: JDK1.8出现的,作用是解决一个类上不能标注重复的注解 ...
- Python面向对象基础一
公司可能过一两个月就要从深圳搬到东莞松山湖,项目组的现在有的在转Java或其他语言的,问我们要不要转java+hoodap+spark方向,我还是先不转,毕竟之前是从ios转回C#,这现在在转其他的那 ...
- Netty 高性能之道 FastThreadLocal 源码分析(快且安全)
前言 Netty 作为高性能框架,对 JDK 中的很多类都进行了封装了和优化,例如 Thread 类,Netty 使用了 FastThreadLocalRunnable 对所有 DefaultThre ...
- EasyUI 添加一行的时候 行号出现负数的解决方案
原因是:在jquery_easyui.js 看方法 insertRow : function(_736, _737, row) 以下小代码算行号,if (opts.pagination) { _73c ...
- Java JDBC的基础知识(五)
本文主要记录JDBC基础知识之后的部分内容.另外,我看到<Java核心基础2>中第四章是主要介绍数据库编程的.里面有一些说明和应用特别灵活,有些部分也太容易理解,建议大家看一下.这篇是依然 ...