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引擎动态编译代码的更多相关文章

  1. 基于 Roslyn 实现动态编译

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

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

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

  3. C#动态编译代码,执行一个代码片段,或者从指定文件中加载某个接口的实现类

    在项目进行中有时候会需要配置一些复杂的表达式,在程序运行的时候执行表达式,根据结果执行相应的操作,简单写了一个类Expression,利用.net的动态编译技术实现,代码如下: public clas ...

  4. 用eval 动态编译代码

    eval 有另外一种用法, 其参数是作为一个字串表达式, 而不是代码块.在运行时, 它将字串临时编译成代码并且执行. 这很易用, 但也很危险, 因为有可能会把具有危害性的代码放到字串里. foreac ...

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

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

  6. ZKWeb网站框架的动态编译的实现原理

    ZKWeb网站框架是一个自主开发的网页框架,实现了动态插件和自动编译功能. ZKWeb把一个文件夹当成是一个插件,无需使用csproj或xproj等形式的项目文件管理,并且支持修改插件代码后自动重新编 ...

  7. 让C#语言充当自身脚本!——.NET中的动态编译

    原文:让C#语言充当自身脚本!--.NET中的动态编译 代码的动态编译并执行是.NET平台提供给我们的很强大的一个工具,用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码 ...

  8. 分享基于.NET动态编译&Newtonsoft.Json封装实现JSON转换器(JsonConverter)原理及JSON操作技巧

    看文章标题就知道,本文的主题就是关于JSON,JSON转换器(JsonConverter)具有将C#定义的类源代码直接转换成对应的JSON字符串,以及将JSON字符串转换成对应的C#定义的类源代码,而 ...

  9. .Net 动态编译(c# 脚本)

    1 用.NET提供的类动态编译代码字符串,生成DLL存于内存中,加载到程序域 2 用反射的方式调用这个DLL 将要被编译和执行的代码读入并以字符串方式保存声明CSharpCodeProvider对象实 ...

随机推荐

  1. SpringSecurity学习之基于数据库的用户认证

    SpringSecurity给我们提供了一套最基本的认证方式,可是这种方式远远不能满足大多数系统的需求.不过好在SpringSecurity给我们预留了许多可扩展的接口给我们,我们可以基于这些接口实现 ...

  2. GO入门——4. 数组、切片与map

    1. 数组 定义数组的格式:var [n],n>=0 数组长度也是类型的一部分,因此具有不同长度的数组为不同类型 注意区分指向数组的指针和指针数组 //数组的指针 a := [2]int{1, ...

  3. Spring Cloud 使用 FeignClient 启动报错

    我们首先来看一下报错信息 Description: Field businessFeignClient in com.ysc.service.BusinessConfigService require ...

  4. 关于oracle的缓冲区机制与HDFS中的edit logs的某些关联性的思考

    可能大家会问,oracle和HDFS属于不同场景的存储系统,它们之间为什么会有联系呢?确实,从技术本身来看,他们确实无关联,但利用“整体学习”的思想,跳出技术本身,可以发现Oracle的缓冲区和HDF ...

  5. OpenStack 对接 Ceph

    [TOC]   1. Openstack 与 Ceph 1.1. Ceph 简介 Ceph 是当前非常流行的开源分布式存储系统,具有高扩展性.高性能.高可靠性等优点,同时提供块存储服务(RBD).对象 ...

  6. 前端模块化之CommonJS,ES6,AMD,CMD

    最近在搞跨平台解决方案,讨论关于模块划分的问题以及如何尽量多的复用逻辑代码.于是就有了此文章,之前的博客也写过,不过由于主机商跑路,宝贵的资源也就没了,说多了都是泪~ 这里按模块化发展的历史回溯的时间 ...

  7. 使用Spring JPA中Page、Pageable接口和Sort类完成分页排序

    显示时,有三个参数,前两个必填,第几页,一页多少个size,第三个参数默认可以不填. 但是发现这个方法已经过时了,通过查看它的源码发现,新方法为静态方法PageRequest of(page,size ...

  8. 给RadioButtonList绑定Selected的值

    有一个案例,是读取Excel的资料显示于ASP.NET的GridView控件.在GridView控件中,有一列是用RadioButtonList来显示性别信息(男或女). 另外来看看Excel的数据: ...

  9. 在GridView控件内文本框实现TextChanged事件

    本篇是教你实现GridView控件内的TextBox文本框实现自身的TextChanged事件.由于某些功能的需求,GridView控件内嵌TextBox,当TextBox值发生变化时,触发TextC ...

  10. 启用sa账号

    第一部分: 如果在安装的时候选中的是Window身份验证,后来需要SQLServer身份验证登录,那么 一.先用window账号登录数据库 二.启用window身份验证和sql sever身份验证方式 ...