C# Компилятор Roslyn: переменные Dynami c вызывают странный сбой (. NET консольное приложение Core 2.2) - PullRequest
0 голосов
/ 08 мая 2020

Я пытаюсь использовать Rosyln для динамической компиляции некоторого кода в сборку. У меня все это работает с одним исключением: когда я пытаюсь объявить тип как dynamic, я получаю сообщение об ошибке компилятора (от компиляции во время выполнения):

error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

Некоторые исследования, такие как Stack Поток переполнения Использование System.Dynami c в Roslyn - предлагает включить ссылку на Microsoft.CSharp.dll и на атрибут Dynami c, что я и сделал.

Опять же, если я переключите тип текста кода на int, он работает нормально. Требуется пакет NuGet Microsoft.CodeAnalysis.Compilers. Если это важно, я использую консольное приложение с. NET Core 2.2 на Windows.

Для справки, этот код основан на полезном Компиляция и запуск C# Код в среде выполнения .

Есть предложения?


using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;

namespace RoslynTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var assemblyName = "TestLibrary";
            var code = @"
    namespace TestNamespace
    {
        public class TestClass
        {
            public static int Add(dynamic a, int b)  // Works if a is declared as int
            {
                return a+b;
            }
        }
    }";

            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                new[] { syntaxTree },
                new MetadataReference[]
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(DynamicAttribute).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly.Location)
                },
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var memoryStream = new MemoryStream())
            {
                EmitResult result = compilation.Emit(memoryStream);

                if (result.Success)
                {
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = Assembly.Load(memoryStream.ToArray());

                    Type testClassType = assembly.GetType("TestNamespace.TestClass");
                    var addResult = (int)testClassType.GetMethod("Add").Invoke(null, new object[] { 3, 4 });
                    Console.WriteLine($"Result is {addResult}");
                }
                else
                {
                    foreach(var error in result.Diagnostics)
                        Console.WriteLine(error.ToString());
                }

                Console.ReadLine();
            }
        }
    }
}
...