Я пытаюсь использовать 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();
}
}
}
}