.Net Core - CS0012“对象"在未引用的程序集中定义 [英] .Net Core - CS0012 'Object' is defined in an assembly that is not referenced

查看:41
本文介绍了.Net Core - CS0012“对象"在未引用的程序集中定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 .Net Core 的新手,我正在尝试基于它构建一个构建系统.作为该项目的一部分,我创建了一个抽象类,阐明了构建任务应该实现的内容,并将其塞入共享库中.

I'm brand new to .Net Core and I'm trying to build a build system based on it. As part of this project, I've created an abstract class that spells out what a build task should implement, and I've stuffed this into a shared library.

可执行项目引用此库并扫描项目目录以查找特殊命名的目录,然后检查其中是否有任何 .cs 文件.加载这些脚本,然后尝试使用通过 Microsoft.CodeAnalysis 和朋友提供的工具进行编译.

The executable project references this library and scans project directories for a specially named directory, then checks to see if there are any .cs files in there. These scripts are loaded and then compilation is attempted using the tools provided through Microsoft.CodeAnalysis and friends.

在这种背景下,我在编译阶段遇到了一个奇怪的问题:

With that background, here's an odd issue I'm hitting at the compilation stage:

如果我尝试将包含抽象类的共享库作为参考提供给编译过程,则会出现以下错误:

If I attempt to supply the shared library containing the abstract class to the compilation process as a reference, I get the following error:

失败的 CS0012:类型对象"是在未定义的程序集中定义的参考.您必须添加对程序集mscorlib"的引用,版本=4.0.0.0,文化=中性,PublicKeyToken=7cec85d7bea7798e'.

Failed CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.

接着是一堆关于预定义类型的抱怨:

Followed by a bunch complaints about predefined types:

CS0518:未定义或导入预定义类型System.Boolean"CS0518:未定义或导入预定义类型System.Boolean"CS0518:未定义或导入预定义类型System.Void"...等等等等

CS0518: Predefined type 'System.Boolean' is not defined or imported CS0518: Predefined type 'System.Boolean' is not defined or imported CS0518: Predefined type 'System.Void' is not defined or imported ... etc etc.

但是,如果我省略引用,而是将每个共享库的源文件解析为语法树并将它们传递给编译过程,则整个过程会成功,并且我得到一个返回的内存程序集,我可以从中提取类型并实例化.

However, if I omit the reference and instead parse each of the shared library's source files into syntax trees and pass them to the compilation process, the whole process succeeds and I get a returned in-memory assembly I can pull types out of and instantiate.

我已阅读 Google 提供的有关此错误的所有内容,但我不知所措.有人可以启发我解释为什么会发生这种情况,并为我如何实现简单地链接到一个公共共享库的最初目标提供额外的互联网积分吗?

I've read everything on this error that Google has to offer, and I'm at a loss. Can somebody enlighten me as to why this is happening and bonus internet points for how I can accomplish my original goal of simply linking in a common shared library?

相关代码

    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
            }
        }
    }
}

推荐答案

TL;DR
在一天结束时,您需要传递对mscorlib.dll"及其私有变体的引用.这将使上述编译错误消失.这也是 .net core 中的跨平台,因为我已经在 Linux 和 Windows 上测试了这个解决方案.

TL;DR
At the end of the day you need to pass a reference to "mscorlib.dll" and its private variant. This will make the above compilation errors go away. This is also cross-platform in .net core, as I've tested this solution on Linux and Windows.

完整版&代码示例
由于我正在等待帐户删除,我将发布最后一个答案.

Full version & code samples
Since I'm waiting for account deletion, I'll post this last answer.

解决方案是根据其他类型程序集的位置手动包含 mscorlib.dll.像这样:

The solution is to manually include mscorlib.dll based on the location of some other type's assembly. Like this:

// Get the directory of a core assembly. We need this directory to
// build out our platform specific reference to mscorlib. mscorlib
// and the private mscorlib must be supplied as references for
// compilation to succeed. Of these two assemblies, only the private
// mscorlib is discovered via enumerataing assemblies referenced by
// this executing binary.
var dd = typeof(Enumerable).GetTypeInfo().Assembly.Location;
var coreDir = Directory.GetParent(dd);            

List<MetadataReference> references = new List<MetadataReference>
{   
    // Here we get the path to the mscorlib and private mscorlib
    // libraries that are required for compilation to succeed.
    MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "mscorlib.dll"),
    MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)           
};

还有第二个 mscorelib,但其名称以private"为前缀.这是由执行程序集自动引用的,因此无需像上面那样手动生成其路径.

There is a second mscorelib, but its name is prefixed with "private". This is automatically referenced by the executing assembly, so there's no need to manually generate its path like above.

当您从正在执行动态代码编译的执行程序集中提取引用时,您将获得此私有 mscorlib.像这样:

You get this private mscorlib when you pull references from the executing assembly which is doing the dynamic code compilation itself. Like so:

// Enumerate all assemblies referenced by this executing assembly
// and provide them as references to the build script we're about to
// compile.
var referencedAssemblies = Assembly.GetEntryAssembly().GetReferencedAssemblies();
foreach(var referencedAssembly in referencedAssemblies)
{
    var loadedAssembly = Assembly.Load(referencedAssembly);   

    references.Add(MetadataReference.CreateFromFile(loadedAssembly.Location)); 
}

所以现在组装好这些引用,您可以简单地将它们传递给您的代码编译:

So now with these references assembled, you can simply pass them to your code compilation:

// Initialize the compilation with our options, references and the
// already parsed syntax tree of the build script.
CSharpCompilation compilation = CSharpCompilation.Create(
    generatedAssemblyName,
    syntaxTrees: new[] { jobSyntaxTree },
    references: references,
    options: op);           

// Compile and emit new assembly into memory.
var ms = new MemoryStream();
EmitResult result = compilation.Emit(ms);

...瞧,您可以在 .Net 核心中使用 Roslyn 跨平台动态编译代码.

... and voila, you can dynamically compile in-code with Roslyn cross-platform in .Net core.

这篇关于.Net Core - CS0012“对象"在未引用的程序集中定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆