Roslyn没有引用System.Runtime

我正在开发一个项目,我们正在使用Roslyn为我们编译一些模板。 现在,当我编译模板时,我在CompileResult.Diagnostics收到了多个错误。

错误是:

 (21,6): error CS0012: The type 'System.Attribute' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. (21,6): error CS0012: The type 'System.Type' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. 

看到这些错误,我假设我没有正确添加对System.Runtime程序集的引用。 但是,在检查加载的组件后,这似乎是有序的。

 private IEnumerable GetGlobalReferences() { var assemblies = new [] { typeof(System.Object).Assembly, //mscorlib typeof(System.Composition.ExportAttribute).Assembly, //System.Composition (MEF) typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler }; var refs = from a in assemblies select new MetadataFileReference(a.Location); return refs.ToList(); } 

编译本身:

 public void Compile(AssemblyFileInfo assemblyInfo) { Parse(assemblyInfo.Files); var compilation = CSharpCompilation.Create(assemblyInfo.FilePath, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .AddReferences(GetGlobalReferences()) .AddSyntaxTrees(assemblyInfo.SourceCodeSyntaxTrees); assemblyInfo.CompileResult = compilation.Emit(assemblyInfo.FilePath); } 

我错过了一些明显的东西吗 看起来成功编译的所有先决条件都得到满足,但显然它们不是。

作为参考,这是我正在尝试编译的(混淆的)代码段:

 namespace Project.Rules.Generated { using System; using System.Runtime; using System.Composition; using System.CodeDom.Compiler; [Export(typeof(IProject))] [GeneratedCode("Project Template Compiler", "1.0")] public sealed class ProcessPriorityValue : ProjectConcreteClass { public override void Execute(ProjectExecutionContext ctx) { CurrentContext = ctx; } } } 

编辑我在搜索中有所提升。 错误消息中指定的PublicKeyToken与System.Composition程序集的PublicKeyToken匹配。 我的猜测是添加所有程序集都可能解决问题。 这是正确的,或者至少是解决方案的一部分。 通过使用dotPeek,我能够检查不同程序集中存在哪些对象。 有了这些知识,我已经将GetGlobalReferences()方法更改为:

 private IEnumerable GetGlobalReferences() { var assemblies = new [] { typeof(System.Object).Assembly, //mscorlib typeof(System.Composition.ExportAttribute).Assembly, //System.Composition.AttributeModel typeof(System.Composition.Convention.ConventionBuilder).Assembly, //System.Composition.Convention typeof(System.Composition.Hosting.CompositionHost).Assembly, //System.Composition.Hosting typeof(System.Composition.CompositionContext).Assembly, //System.Composition.Runtime typeof(System.Composition.CompositionContextExtensions).Assembly, //System.Composition.TypedParts typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler }; var refs = from a in assemblies select new MetadataFileReference(a.Location); return refs.ToList(); } 

如您所见,我现在通过指定程序集中存在的对象添加所有System.Composition程序集。 通过添加System.Composition.Runtime ,我的编译错误得到了解决。

这确实引入了不同的错误。 你可以自己查看一下, System.Composition.Runtime有一个通用的Export类: public sealed class Export : IDisposable因为这个我现在收到这个错误:

 (21,6): error CS0404: Cannot apply attribute class 'System.Composition.Export' because it is generic 

由于某种原因,代码现在想要使用System.Composition.Runtime.Export而不是在System.Composition.AttributeModel程序集中定义的ExportAttribute。

EDIT2

我可以确认上面的代码使用System.Composition.Export而不是ExportAttribute 。 我通过将[Export(typeof(IProject)]更改为[ExportAttribute(typeof(IProject)]来发现这一点。由于此更改,原始错误返回。看起来像程序集System.Composition.AttributeModel未加载/引用正确,但在检查compilation ,我可以看到程序集被引用了。

我目前得到的参考组件是:

 + [0] mscorlib, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity + [1] System.Composition.AttributedModel, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [2] System.Composition.Convention, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [3] System.Composition.Hosting, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [4] System.Composition.Runtime, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [5] System.Composition.TypedParts, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [6] Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity + [7] System, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity + [8] System.Core, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity + [9] System.Data, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity 

您似乎正在引用PortableClassLibrary。 Portable Class Libraries从“System.Runtime.dll”中获取一些基本类型(如object / string / etc)。 但是,在桌面框架中,这些来自mscorlib.dll。 当您使用typeof(object).Assembly ,您将获得Roslyn自己的object版本。 由于Roslyn不是构建为可移植类库,而是来自mscorlib,并且与其他引用的标识不匹配。

根据Dejan在评论部分的要求,我会将答案(我的问题)作为一个真正的答案发布。


我发现了问题所在! 编译器一直都是正确的。 smack0007的一篇博 文引发了我尝试别的东西。 而不是使用Facade DLL,尝试手动引用必要的DLL。 GetGlobalReferences方法现在看起来像这样:

 private IEnumerable GetGlobalReferences() { var assemblies = new [] { /*Making sure all MEF assemblies are loaded*/ typeof(System.Composition.Convention.AttributedModelProvider).Assembly, //System.Composition.AttributeModel typeof(System.Composition.Convention.ConventionBuilder).Assembly, //System.Composition.Convention typeof(System.Composition.Hosting.CompositionHost).Assembly, //System.Composition.Hosting typeof(System.Composition.CompositionContext).Assembly, //System.Composition.Runtime typeof(System.Composition.CompositionContextExtensions).Assembly, //System.Composition.TypedParts /*Used for the GeneratedCode attribute*/ typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler }; var refs = from a in assemblies select new MetadataFileReference(a.Location); var returnList = refs.ToList(); //The location of the .NET assemblies var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location); /* * Adding some necessary .NET assemblies * These assemblies couldn't be loaded correctly via the same construction as above, * in specific the System.Runtime. */ returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "mscorlib.dll"))); returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.dll"))); returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.Core.dll"))); returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.Runtime.dll"))); return returnList; } 

在反编译System.Runtime.dll我也看到了为什么它无法以任何其他方式引用。 dll是空的,它只包含对其他程序集的一些引用。 因此,不能以任何其他方式引用该组件。