在Roslyn中加载可移植MetadataReference的正确方法是什么?

时间:2015-10-06 04:11:31

标签: c# .net 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
}

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

MetadataReference.CreateFromFile(typeof(object).Assembly.Location),

我得到以下例外情况:

  

CS0012:类型'对象'在一个不是的程序集中定义   引用。您必须添加对程序集&System; System.Runtime的引用,   Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'。

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

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

2 个答案:

答案 0 :(得分:4)

如果您的编译引用了“完整”框架4.5或4.6,并且您还引用了可移植库,则还需要添加对façade程序集的引用以在它们之间进行桥接。您可以在以下网址找到它们:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\Facades

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

答案 1 :(得分:1)

找到程序集的路径并指定要加载的可移植库。可能看起来像这样:

var dotNetAssemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
var references = new MetadataReference[]
    {
        MetadataReference.CreateFromFile(Path.Combine(dotNetAssemblyPath, "MY_PORTABLE_FILE_TO_BE_LOADED"))
    };