罗斯林没有提到System.Runtime
本文关键字:System Runtime 罗斯林 | 更新日期: 2023-09-27 18:05:43
我正在做一个项目,我们正在使用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<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();
}
和编译本身:
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与系统的PublicKeyToken匹配。复合组件。我的猜测是添加所有的程序集可能解决这个问题。这是正确的,或者至少是解决方案的一部分。通过使用dotPeek,我能够检查哪些对象存在于不同的程序集中。有了这些知识,我已经改变了GetGlobalReferences()
方法如下:
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();
}
如您所见,我正在添加所有System。现在通过指定程序集中存在的对象来组合程序集。通过添加System.Composition.Runtime
,解决了我的编译错误。
这确实引入了一个不同的错误。你可以自己检查,在System.Composition.Runtime
中有一个通用的Export类:public sealed class Export<T> : IDisposable
因为这个,我现在得到这个错误:
(21,6): error CS0404: Cannot apply attribute class 'System.Composition.Export<T>' because it is generic
由于某些原因,代码现在想使用System.Composition.Runtime.Export<T>
而不是在System.Composition.AttributeModel
程序集中定义的ExportAttribute。
edit2
我可以确认上面的代码使用了System.Composition.Export<T>
而不是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
应Dejan在评论区的要求,我将把答案(对我的问题)作为一个真正的答案发布出来。
我发现问题是什么了!编译器一直都是正确的。一篇关于smack0007的博客文章促使我尝试其他东西。与其使用Facade dll,不如尝试手动引用必要的dll。GetGlobalReferences
方法现在看起来像这样:
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;
}
当反编译System.Runtime.dll
时,我也看到了为什么它不能以任何其他方式引用。dll是空的,它只包含对其他程序集的一些引用。因此,不能以任何其他方式引用该程序集。
看起来您正在引用PortableClassLibrary。可移植类库从"System.Runtime.dll"中获取一些基本类型(如对象/字符串等)。然而,在桌面框架中,这些来自mscorlib.dll。当你使用typeof(object).Assembly
时,你会得到Roslyn自己的object
版本。由于Roslyn不是作为可移植类库构建的,它是来自mscorlib的,并且不匹配您的其他引用的身份。
预定义的引用列表不适合我。
但是从AppDomain
获得它们是有帮助的:
public static readonly List<PortableExecutableReference> References =
AppDomain.CurrentDomain.GetAssemblies()
.Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location))
.Select(_ => MetadataReference.CreateFromFile(_.Location))
.Concat(new[]
{
// add your app/lib specifics, e.g.:
MetadataReference.CreateFromFile(typeof(MyType).Assembly.Location),
})
.ToList();
我在这个有用的repo中找到了答案:https://github.com/andrewlock/NetEscapades.EnumGenerators