【问题标题】:C# Roslyn .NET CORE 3.1 CSharpCompilation dynamic RuntimeBinder.Binder.Convert ErrorC# Roslyn .NET CORE 3.1 CSharpCompilation 动态 RuntimeBinder.Binder.Convert 错误
【发布时间】:2021-01-09 16:58:12
【问题描述】:

使用 .NET Core 3.1 (Windows) 我正在尝试动态编译一个使用 dynamic 类型的类。我继续收到错误:

error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.Convert'

我已添加对 Microsoft.CSharp 和 System.Linq.Expressions 的引用,但仍然缺少我无法找到的程序集引用。

我已经浏览了有关此错误的所有在线参考资料,我可以在 StackOverflow 和 github 上找到这些参考资料。

一个有趣的提示,这在 .NET Core 5.0 下工作......很遗憾,我还没有准备好升级到 5。

    class Program
    {
        static void Main(string[] args)
        {
            var code = @"
using System;
using System.Collections.Generic;

namespace Debuggable
{
    public class HelloWorld
    {
        public string DoWork()
        {
            var a = ""foo"";

            var map = new Dictionary<string, object>();
            map[""a""] = ""bar"";
    
            if (map.TryGetValue(""a"", out dynamic t))
                a = t;

            return a;
        }
    }
}
            ";

            (byte[] a, byte[] b) = CreateAssembly(code);
            var assembly = Assembly.Load(a, b);

            dynamic instance = assembly.CreateInstance("Debuggable.HelloWorld");
            string result = instance.DoWork();

            Console.WriteLine(result);
        }

        public static (byte[], byte[]) CreateAssembly(string code)
        {
            var encoding = Encoding.UTF8;
            var assemblyName = Path.GetRandomFileName();
            var symbolsName = Path.ChangeExtension(assemblyName, "pdb");

            var references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.CSharp")).Location),
                MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System")).Location),
                MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Runtime")).Location),
                MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Collections")).Location),
                MetadataReference.CreateFromFile(typeof(System.Linq.Expressions.ExpressionType).GetTypeInfo().Assembly.Location),
            };

            var syntaxTrees = new List<SyntaxTree>();
            var embeddedTexts = new List<EmbeddedText>();

            var sourceCodePath = "generated.cs";
            var buffer = encoding.GetBytes(code);
            var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);

            var syntaxTree = CSharpSyntaxTree.ParseText(
                sourceText,
                new CSharpParseOptions().WithLanguageVersion(LanguageVersion.CSharp8),
                path: sourceCodePath);

            var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
            var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);

            syntaxTrees.Add(encoded);
            embeddedTexts.Add(EmbeddedText.FromSource(sourceCodePath, sourceText));

            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees: syntaxTrees,
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                    .WithOptimizationLevel(OptimizationLevel.Debug)
                    .WithPlatform(Platform.AnyCpu)
            );

            using (var assemblyStream = new MemoryStream())
            using (var symbolsStream = new MemoryStream())
            {
                var emitOptions = new EmitOptions(
                    debugInformationFormat: DebugInformationFormat.PortablePdb,
                    pdbFilePath: symbolsName);

                EmitResult result = compilation.Emit(
                    peStream: assemblyStream,
                    pdbStream: symbolsStream,
                    embeddedTexts: embeddedTexts,
                    options: emitOptions);

                if (!result.Success)
                {
                    var errors = new List<string>();

                    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);

                    foreach (Diagnostic diagnostic in failures)
                        errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}");

                    throw new Exception(string.Join("\n", errors));
                }

                return (assemblyStream.GetBuffer(), symbolsStream.GetBuffer());
            }
        }
    }

【问题讨论】:

  • 我认为问题是 var a。你可以试试 object a = ""foo"";而是。

标签: c# .net-core dynamic roslyn


【解决方案1】:

我能够使用 MSBuild 添加的引用来缩小范围。如果其他人在 .NET Core 3.1 中遇到这种情况,他们就在这里。

MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.CSharp")).Location),
MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("netstandard")).Location),
MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Linq.Expressions")).Location),
MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Private.CoreLib")).Location),
MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Runtime")).Location),

另外,我注意到如果通过显式文件路径加载程序集,所需的引用集是不同的。区别在于\dotnet\packs\dotnet\shared 程序集。不过,我对此了解的不够多,无法说明原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 2020-09-12
    • 2017-01-08
    • 1970-01-01
    • 2021-07-27
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多