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

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

问题描述

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



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



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



如果我尝试向编译过程提供包含抽象类的共享库作为参考,我收到以下错误:


失败的CS0012:类型'Object'是在未引用
的程序集中定义的。您必须添加对程序集'mscorlib,
Version = 4.0.0.0,Culture = neutral,PublicKeyToken = 7cec85d7bea7798e'的引用。


接下来是关于预定义类型的抱怨:


CS0518:未定义或导入了预定义类型'System.Boolean'
CS0518:未定义或导入预定义类型'System.Boolean'
CS0518:未定义或导入预定义类型'System.Void'...


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



我已经阅读了有关Google必须提供的该错误的所有信息,现在损失。有人能启发我为什么会这样,并为我如何实现我简单地连接到公共共享库中的最初目标提供额外的互联网积分吗?



相关代码

  CSharpParseOptions parseOptions = CSharpParseOptions.Default; 

SyntaxTree jobSyntaxTree = CSharpSyntaxTree.ParseText(scriptContents,parseOptions);

生成的字符串AssemblyName = Path.GetRandomFileName();
var referencedAssemblies = Assembly.GetEntryAssembly()。GetReferencedAssemblies();

foreach(varededAssemblies中的var referencedAssembly)
{
var rfas = Assembly.Load(referencedAssembly);
reference.Add(MetadataReference.CreateFromFile(rfas.Location));
}

var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

CSharpCompilation编译= CSharpCompilation.Create(
generateAssemblyName,
语法树:new [] {jobSyntaxTree},
引用:引用,
选项:op) ;

var ms = new MemoryStream();

EmitOptions glowOptions = new EmitOptions();

EmitResult结果= compile.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
}
}
},
configuration:{
Debug:{
buildOptions:{
define:[
DEBUG,
TRACE
],
optimize:假,
preserveCompilationContext:真
}
},
发布:{
buildOptions:{
define:[
RELEASE,
TRACE
],
optimize:true,
reserveCompilationContext:真
}
}
}
}

主要可执行文件的Project.json

  {
version: 1.0.0-*,
buildOptions:{
emitEntryPoint:true,
preserveCompilationContext:true
},
dependencies:{
Microsoft.NE TCore.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。兼容性: 1.0.1,
BuildBotCore: 1.0.0-*
},
框架:{
netcoreapp1.0:{
进口: netcore50,
buildOptions:{
preserveCompilationContext:真
}
}
},
configuration:{
Debug:{
buildOptions:{
define:[
DEBUG,
TRACE
],
optimize:否,
preserveCompilationContext:true
}
},
Release:{
buildOptions: {
定义:[
释放,
跟踪
],
优化:true,
preserveCompilationContext:true
}
}
}
}


解决方案

TL; DR

最终,您需要传递对 mscorlib.dll及其私有变体的引用。这将使上述编译错误消失。

完整版&代码示例

由于我正在等待帐户删除,因此我将发布最后一个答案。



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

  //获取核心程序集的目录。我们需要该目录到
//建立对mscorlib的平台特定引用。 mscorlib
//和必须提供私有mscorlib作为
//编译成功的参考。在这两个程序集中,只有私有的
// mscorlib是通过枚举
//此执行二进制文件引用的程序集而发现的。
var dd = typeof(Enumerable).GetTypeInfo()。Assembly.Location;
var coreDir = Directory.GetParent(dd);

List< MetadataReference>引用=新的List< MetadataReference>。
{
//这里我们获得编译成功所需的mscorlib和私有mscorlib
//的路径。
MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + mscorlib.dll),
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo()。Assembly.Location)
};

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



当您从执行程序集中提取引用时,会得到此私有的mscorlib。在做动态代码编译本身。像这样:

  //枚举此执行程序集引用的所有程序集
//并提供它们作为对构建脚本,我们将要
//进行编译。
var referencedAssemblies = Assembly.GetEntryAssembly()。GetReferencedAssemblies();
foreach(varededAssemblies中的var referencedAssembly)
{
var loadAssembly = Assembly.Load(referencedAssembly);

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

因此,现在将这些引用组装在一起,您只需将它们传递给代码编译即可:

  //使用我们的选项,引用和
//初始化的语法树初始化编译脚本。
CSharpCompilation编译= CSharpCompilation.Create(
generateAssemblyName,
语法树:new [] {jobSyntaxTree},
引用:引用,
选项:op);

//编译并将新程序集发出到内存中。
var ms = new MemoryStream();
EmitResult结果= compile.Emit(ms);

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


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.

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:

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: 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.

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?

Relevant code

    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 file for the shared library

{
    "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 for main executable

{
    "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
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.

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

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.

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);

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

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

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