在 Roslyn 中加载便携式 MetadataReference 的正确方法是什么?

Joh*_*ner 3 .net c# roslyn

我正在尝试编译一些针对可移植 .Net 库构建的代码,并且我正在尝试确定将可移植程序集作为MetadataReference对象加载的正确方法。

例如,我可以像这样加载程序集,它会起作用:

var analyzerCode = "// Some analyzer code here";
var syntaxTree = CSharpSyntaxTree.ParseText(analyzerCode);

string assemblyName = System.IO.Path.GetRandomFileName();
MetadataReference[] references = new MetadataReference[]
{
    MetadataReference.CreateFromFile(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.dll"),
    MetadataReference.CreateFromFile(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Diagnostics.Debug.dll"),
    MetadataReference.CreateFromFile(typeof(System.Collections.Immutable.ImmutableArray).Assembly.Location),
    MetadataReference.CreateFromFile(typeof(Microsoft.CodeAnalysis.CSharp.CSharpCompilation).Assembly.Location),
    MetadataReference.CreateFromFile(typeof(Microsoft.CodeAnalysis.Workspace).Assembly.Location)
};

CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

using (var ms = new MemoryStream())
{
    EmitResult result = compilation.Emit(ms);
    // Check the result for errors and work with it
}
Run Code Online (Sandbox Code Playgroud)

显然,这不是非常可移植的代码,因为我使用的文件路径可能仅适用于我的机器。如果我执行以下操作:

MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
Run Code Online (Sandbox Code Playgroud)

我得到以下例外:

CS0012:在未引用的程序集中定义了类型“对象”。您必须添加对程序集“System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”的引用。

我相信这是因为运行此代码的解决方案是 4.6 程序集,因此typeof(object)指向 4.6 System.dll。

所以我的问题是,指定可移植程序集用作MetadataReferenceRoslyn 编译对象的实例的正确方法是什么?

Jas*_*ski 5

如果您的编译引用了“完整”框架 4.5 或 4.6,并且您还引用了可移植库,则还需要添加对外观程序集的引用以在它们之间建立桥梁。您可以在以下位置找到它们:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades
Run Code Online (Sandbox Code Playgroud)

您应该将 v4.6 替换为您所针对的桌面框架的任何版本。您应该循环遍历该目录并为您在其中看到的所有程序集添加一个引用。