ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用 Roslyn引擎动态编译代码

2021-06-06 10:52:24  阅读:207  来源: 互联网

标签:Assembly diagnostic 编译 引擎 result ms Roslyn new


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(0, 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(0, SeekOrigin.Begin);
            assembly = Assembly.Load(ms.ToArray());
        }
    }
    return assembly;
}

 

标签:Assembly,diagnostic,编译,引擎,result,ms,Roslyn,new
来源: https://blog.51cto.com/XCracker/2871728

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有