C# 无法从源代码在Roslyn中创建编译
出于测试目的,我需要从包含源代码的字符串C# 无法从源代码在Roslyn中创建编译,c#,.net,reflection,roslyn,roslyn-code-analysis,C#,.net,Reflection,Roslyn,Roslyn Code Analysis,出于测试目的,我需要从包含源代码的字符串source中获取System.Reflection.Assembly。我正在使用Roslyn: SyntaxTree tree = CSharpSyntaxTree.ParseText(source); CSharpCompilation compilation = CSharpCompilation.Create("TestCompilation", new[] { tree }); Assembly assembly = null; using (
source
中获取System.Reflection.Assembly
。我正在使用Roslyn:
SyntaxTree tree = CSharpSyntaxTree.ParseText(source);
CSharpCompilation compilation = CSharpCompilation.Create("TestCompilation", new[] { tree });
Assembly assembly = null;
using (var stream = new MemoryStream())
{
var emitResult = compilation.Emit(stream);
if (!emitResult.Success)
{
var message = emitResult.Diagnostics.Select(d => d.ToString())
.Aggregate((d1, d2) => $"{d1}{Environment.NewLine}{d2}");
throw new InvalidOperationException($"Errors!{Environment.NewLine}{message}");
}
stream.Seek(0, SeekOrigin.Begin);
assembly = Assembly.Load(stream.ToArray());
}
正如您所看到的,我在这里的尝试是发出一个csharpcomilation
对象,以便稍后获得程序集。我正试图通过以下方式做到这一点:
var source = @"
namespace Root.MyNamespace1 {
public class MyClass {
}
}
";
发出错误
但是我在var emitResult=compilation.Emit(stream)
失败,并输入显示错误的条件。我收到1个警告和3个错误:
- 警告CS8021:找不到RuntimeMetadataVersion的值。未找到包含System.Object的程序集,也未通过选项指定RuntimeMetadataVersion的值
- (3,34):错误CS0518:未定义或导入预定义类型“System.Object”
- (3,34):错误CS1729:“对象”不包含接受0个参数的构造函数
- 错误CS5001:程序不包含适合入口点的静态“Main”方法
因此,我似乎需要添加对mscorelib
的引用,而且我还需要告诉Roslyn我想要发出一个类库,而不是一个可执行程序集。如何操作?您缺少对mscorlib
的元数据引用,您可以通过csharpcomilationoptions
更改编译选项
按如下方式创建编译:
var Mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
var compilation = CSharpCompilation.Create("TestCompilation",
syntaxTrees: new[] { tree }, references: new[] { Mscorlib }, options: options);
要从非netstandard代码创建netstandard库(在我的例子中,我是从core3.1创建netstandard库),代码应该是
var compilation = CSharpCompilation.Create("TestCompilation",
syntaxTrees: new[] {
tree
},
references: new[] {
MetadataReference.CreateFromFile(@"C:\Users\YOURUSERNAME\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll"
},
options:
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
这里的关键是路径。
由于主机代码是core3.1,因此不能使用MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
,因为它引用的是core3.1对象,而不是netcore2.0对象
参考nuget软件包(现在)时,可将其下载到%USERPROFILE%\.nuget\packages
文件夹,然后从那里加载。这不适用于任何其他用户,因此必须设计不同的解决方案。可以利用,但这可能不适用于CI/CD
MetadataReference.CreateFromFile( Path.Combine(
UserProfilePath, ".nuget", "packages", "netstandard.library", "2.0.3", "build",
"netstandard2.0", "ref", "netstandard.dll"))
更新:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile)
不适用于CI/CD
MetadataReference.CreateFromFile( Path.Combine(
UserProfilePath, ".nuget", "packages", "netstandard.library", "2.0.3", "build",
"netstandard2.0", "ref", "netstandard.dll"))
请参阅构建。因此,动态地将源字符串转换为c代码,然后查询名称空间的..有关缺少引用的部分mscorlib
这可能是一个解决方案: