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

问题描述 投票:0回答:3

我正在尝试编译一些针对可移植 .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.Runtime”的引用, 版本=4.0.0.0,文化=中立,PublicKeyToken=b03f5f7f11d50a3a'。

我相信这是因为运行此代码的解决方案是 4.6 程序集,因此

typeof(object)
指向 4.6 System.dll。

所以我的问题是,指定可移植程序集用作 Roslyn 编译对象的

MetadataReference
实例的正确方法是什么?

c# .net roslyn
3个回答
5
投票

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

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

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


2
投票

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

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

0
投票

使用以下 nuget 包:

https://github.com/jaredpar/basic-reference-assemblies

参考:https://github.com/dotnet/roslyn/issues/49498

此存储库现在构建易于使用的参考程序集 DLL。 README.md 有很多细节,但简而言之,使用那里定义的 NuPkg,您可以在内存编译中创建,如下所示:

var code = @"
using System;
static class Program
{
    static void Main()
    {
        var tuple = (Part1: ""hello"", Part2: ""world"");
        Console.WriteLine($""{tuple.Part1} {tuple.Part2}"");
    }
}
";

var compilation = CSharpCompilation
    .Create(
        "HelloWorld.dll",
        new[] { CSharpSyntaxTree.ParseText(code) },
        references: ReferenceAssemblies.Net50);

using var fileStream = new FileStream(@"p:\temp\helloworld.exe", FileMode.Create, FileAccess.ReadWrite);
var emitResults = compilation.Emit(fileStream);
© www.soinside.com 2019 - 2024. All rights reserved.