Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn has no reference to System.Runtime

Tags:

I'm working on a project where we are using Roslyn to compile some templates for us. Now when I'm compiling the template I'm receiving multiple errors in the CompileResult.Diagnostics.

The errors are:

(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'. 

Seeing these errors I assumed I didn't add a reference to the System.Runtime assembly correctly. However, after checking the loaded assemblies this appears to be in order.

private IEnumerable<MetadataReference> 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(); } 

And the compilation itself:

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

Am I missing something obvious? It looks like all the prerequisites for a successfull compilation are satisfied, but apparently they aren't.

For reference, this is the (obfuscated) piece of code I'm trying to compile:

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

edit I've advanced in my searchings a bit. The PublicKeyToken specified in the error messages match the PublicKeyToken of the System.Composition assemblies. My guess was adding all of the assemblies could possibly fix the issue. This is correct, or at least part of the solution. By using dotPeek I was able to check which objects exist in the different assemblies. With this knowledge I've changed the GetGlobalReferences() method to this:

private IEnumerable<MetadataReference> 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(); } 

As you can see, I'm adding all System.Composition assemblies now by specifying an object which exists in the assembly. By adding the System.Composition.Runtime, my compile errors were solve.

This did introduce a different error though. As you can check out yourself, there is a generic Export class in System.Composition.Runtime: public sealed class Export<T> : IDisposable Because of this I'm now getting this error:

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

For some reason the code now wants to use System.Composition.Runtime.Export<T> and not the ExportAttribute, defined in System.Composition.AttributeModel assembly.

edit2

I can confirm the above code uses the System.Composition.Export<T> and not the ExportAttribute. I discovered this by changing the [Export(typeof(IProject)] to [ExportAttribute(typeof(IProject)]. Because of this change, the original errors returned. It looks like the assembly System.Composition.AttributeModel isn't loaded/referenced correctly, but after checking the compilation, I can see the assembly is referenced ok.

Referenced assemblies I've got at the moment are:

+       [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 
like image 609
Jan_V Avatar asked May 28 '14 09:05

Jan_V


1 Answers

By request of Dejan in the comment section, I'll post the answer (to my problem) as a real answer.


I've found out what the problem was! The compiler was correct all along. A blog post of smack0007 triggered me of trying something else. Instead of using the Facade dll, try referencing the necessary dll's manually. The GetGlobalReferences method now looks like this:

private IEnumerable<MetadataReference> 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; } 

When decompiling the System.Runtime.dll I also saw why it couldn't be referenced in any other way. The dll is empty, it only contains some references to other assemblies. Therefore one can't reference this assembly in any other way.

like image 197
Jan_V Avatar answered Oct 04 '22 10:10

Jan_V