Roslyn(一) 动态编译

3 篇文章 1 订阅

NET 编译器平台(.NET Compiler Platform)

也称为Roslyn,是Microsoft的一组用于C#和Visual Basic (VB.NET) 语言的开源 编译器和代码分析 API。

该项目特别包括C# 和 VB.NET 编译器的自托管版本——用语言本身编写的编译器。编译器可通过传统的命令行程序使用,也可作为 API 在 .NET 代码中本地使用。Roslyn 公开了用于代码句法(词法)分析、语义分析、CIL动态编译和代码发射的模块。

例子

下面是一个简单的例子,来简单的使用。

创建一个C#控制台程序,引用下面的包。

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.6.0" />
  </ItemGroup>

这里放入了两个脚本代码,展示如何运行。

直接上代码

using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Emit;
using System.Reflection;

namespace RoslynCosonle
{
    class Program
    {
        static string code0 = @"
            using System;
            namespace RoslynCompileSample
            {
                public class Fun
                {
                    public static string GetName()
                    {
                        return ""Get Fun.Name"";
                    }
                }
            }";
        static string code1 = @"
            using System;
            namespace RoslynCompileSample
            {
                public class Writer
                {
                    public void Write(string message)
                    {
                        Console.WriteLine(message);
                        Console.WriteLine(Fun.GetName());
                    }
                }
            }";
        static void Main(string[] args)
        {

            // 随机程序集名称
            string assemblyName = Path.GetRandomFileName();
            Console.WriteLine("assemblyName:" + assemblyName);
            //Debug.WriteLine("assemblyName : "+assemblyName);
            // 元数据引用
            var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
            Console.WriteLine("assemblyPath:" + assemblyPath);
            MetadataReference[] references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Private.CoreLib.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Console.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll"))

        };

            SyntaxTree[] syntaxTree =
            {
                
                CSharpSyntaxTree.ParseText(code1),
                CSharpSyntaxTree.ParseText(code0)
            };

            // 创建编译对象
            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees: 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" });

                }
            }


        }
    }

}

执行结果
在这里插入图片描述

其他资料

引用和参考1
引用和参考2
引用和参考3
引用和参考4
引用和参考5

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值