C# Roslyn .NET CORE 3.1 CSharpCompilation 动态 RuntimeBinder.Binder.Convert 错误
C# Roslyn .NET CORE 3.1 CSharpCompilation dynamic RuntimeBinder.Binder.Convert Error
使用 .NET Core 3.1 (Windows) 我正在尝试动态编译使用 dynamic
类型的 class。我继续收到错误消息:
error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.Convert'
我已经添加了对 Microsoft.CSharp 和 System.Linq.Expressions 的引用,但仍然缺少我无法找到的程序集引用。
我已经浏览了我可以在 Whosebug 上找到的所有在线参考资料,并且 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());
}
}
}
我能够使用 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
程序集。我对此了解不多,无法说明原因。
使用 .NET Core 3.1 (Windows) 我正在尝试动态编译使用 dynamic
类型的 class。我继续收到错误消息:
error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.Convert'
我已经添加了对 Microsoft.CSharp 和 System.Linq.Expressions 的引用,但仍然缺少我无法找到的程序集引用。
我已经浏览了我可以在 Whosebug 上找到的所有在线参考资料,并且 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());
}
}
}
我能够使用 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
程序集。我对此了解不多,无法说明原因。