【发布时间】:2016-08-14 15:52:09
【问题描述】:
我是 .Net Core 的新手,我正在尝试基于它构建一个构建系统。作为该项目的一部分,我创建了一个抽象类来说明构建任务应该实现的内容,并将其填充到一个共享库中。
可执行项目引用此库并扫描项目目录以查找特殊命名的目录,然后检查其中是否有任何.cs 文件。加载这些脚本,然后使用Microsoft.CodeAnalysis 和朋友提供的工具尝试编译。
在这样的背景下,我在编译阶段遇到了一个奇怪的问题:
如果我尝试将包含抽象类的共享库作为参考提供给编译过程,则会收到以下错误:
失败的 CS0012:“对象”类型是在不是 参考。您必须添加对程序集“mscorlib”的引用, 版本=4.0.0.0,文化=中性,PublicKeyToken=7cec85d7bea7798e'。
接着是一堆关于预定义类型的抱怨:
CS0518:未定义或导入预定义类型“System.Boolean” CS0518:未定义或导入预定义类型“System.Boolean” CS0518:未定义或导入预定义类型“System.Void”... 等等等等。
但是,如果我省略引用,而是将每个共享库的源文件解析为语法树并将它们传递给编译过程,那么整个过程就会成功,并且我会得到一个返回的内存程序集,我可以从中提取类型并实例化。
我已经阅读了 Google 提供的有关此错误的所有内容,但我不知所措。有人能告诉我为什么会发生这种情况,以及如何实现我最初的目标,即简单地链接到一个公共共享库中吗?
相关代码
CSharpParseOptions parseOptions = CSharpParseOptions.Default;
SyntaxTree jobSyntaxTree = CSharpSyntaxTree.ParseText(scriptContents, parseOptions);
string generatedAssemblyName = Path.GetRandomFileName();
var referencedAssemblies = Assembly.GetEntryAssembly().GetReferencedAssemblies();
foreach(var referencedAssembly in referencedAssemblies)
{
var rfas = Assembly.Load(referencedAssembly);
references.Add(MetadataReference.CreateFromFile(rfas.Location));
}
var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
CSharpCompilation compilation = CSharpCompilation.Create(
generatedAssemblyName,
syntaxTrees: new[] { jobSyntaxTree },
references: references,
options: op);
var ms = new MemoryStream();
EmitOptions emitOptions = new EmitOptions();
EmitResult result = compilation.Emit(ms);
if(result.Success)
{
// Yay
}
else
{
// Boo-hoo
}
共享库的 Project.json 文件
{
"title": "BuildBotCore",
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": false,
"preserveCompilationContext": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"System.Runtime": "4.1.0",
"System.Runtime.Loader": "4.0.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "netcore50",
"buildOptions": {
"preserveCompilationContext": true
}
}
},
"configurations": {
"Debug": {
"buildOptions": {
"define": [
"DEBUG",
"TRACE"
],
"optimize": false,
"preserveCompilationContext": true
}
},
"Release": {
"buildOptions": {
"define": [
"RELEASE",
"TRACE"
],
"optimize": true,
"preserveCompilationContext": true
}
}
}
}
主要可执行文件的 Project.json
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"System.Runtime": "4.1.0",
"Microsoft.CodeAnalysis.CSharp": "1.3.2",
"System.Runtime.Loader": "4.0.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
"BuildBotCore": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "netcore50",
"buildOptions": {
"preserveCompilationContext": true
}
}
},
"configurations": {
"Debug": {
"buildOptions": {
"define": [
"DEBUG",
"TRACE"
],
"optimize": false,
"preserveCompilationContext": true
}
},
"Release": {
"buildOptions": {
"define": [
"RELEASE",
"TRACE"
],
"optimize": true,
"preserveCompilationContext": true
}
}
}
}
【问题讨论】:
-
这表明您正在尝试从 .NET Core 引用 .NET Framework 程序集。这是行不通的,因为 .NET Framework 有更多可用的原语,因此可以完成很多 .NET Core 无法完成的事情。请参阅Referencing mscorlib 4.0.0.0 from .NET Core 1.0 class library 了解类似患者的回复。
-
@bartonjs 谢谢。有趣的是,在所有引用的程序集中,唯一导致此错误出现的是我项目中的 .net 核心共享库。正如我在问题中提到的,当我删除该参考编译成功时。然而,这是我专门针对 .net 核心创建的程序集,嵌入的
TargetFrameworkAttribute证实了这一点。此外,当我直接加载它的所有源代码进行编译而不是引用程序集时,它编译时不会出错。真是令人费解。 -
您可以发布您的项目和共享库的
project.json吗? -
可疑之处:没有理由提及 System.Runtime,包含在 NetStandard.Library 和 Microsoft.NETCore.App 元包中。 BuildBotCore 应该被称为项目依赖项。在没有用例的情况下添加了兼容性程序集。两个库都声明为 netcoreapp,这至少很奇怪。
-
@Thomas 我已经发布了答案。事实证明,这一切都是由于必须手动获取对
mscorlib的引用以及在编译期间提供执行程序集引用的私有mscorlib作为引用引起的。这消除了所有这些错误,代码在 Windows 和 Linux 上按预期工作,我可以舀出.cs文件并即时编译它们。