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. text_edit 未定义解决

    找到文件:admin\controller\setting $data['heading_title'] = $this->language->get('heading_title'); ...

  2. 移动键盘 滚动input

    window.addEventListener('resize', function () { if(document.activeElement.tagName === 'INPUT'){ docu ...

  3. Spring mvc 4系列教程(一)

    一.Spring框架概览 Spring框架是一种轻量级.一站式解决企业级应用的解决方案.不仅如此,Spring的模块化的特点,可以使你只引用所需要的部分,而无需引用全部.你可以使用控制反转容器(IoC ...

  4. mysql pdo设置显示报错

    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    

  5. [机器学习] 训练集(train set) 验证集(validation set) 测试集(test set)

    在有监督(supervise)的机器学习中,数据集常被分成2~3个即: 训练集(train set) 验证集(validation set) 测试集(test set) 一般需要将样本分成独立的三部分 ...

  6. (转)mybatis-plus入门

    目前正在维护的公司的一个项目是一个ssm架构的java项目,dao层的接口有大量数据库查询的方法,一个条件变化就要对应一个方法,再加上一些通用的curd方法,对应一张表的dao层方法有时候多达近20个 ...

  7. jQuery.Ajax()执行WCF Service的方法

    Insus.NET有在上一篇<ASP.NET MVC呼叫WCF Service的方法>http://www.cnblogs.com/insus/p/3720547.html 直接呼叫WCF ...

  8. 反射实现Model修改前后的内容对比

    在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 public class User { priv ...

  9. 【Java并发编程】10、Java 理论与实践: 正确使用 Volatile 变量

    转自:http://www.importnew.com/15842.html Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchron ...

  10. 卡片游戏(hdu4550)贪心

    卡片游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submi ...