【问题标题】:Roslyn seems to ignore some metadata referencesRoslyn 似乎忽略了一些元数据引用
【发布时间】:2020-01-28 09:23:23
【问题描述】:

在一些集成测试的准备阶段,我必须动态生成一些引用其他程序集的程序集并将它们刷新到磁盘。我猜这个任务的明显选择是 Roslyn。 Roslyn 编译成功完成并将发出的程序集保存到磁盘。当我使用 ILSPy 检查结果时,我发现一些程序集引用不包括在内。

虚拟类生成代码:

public static string GenerateEmptyPublicClass([NotNull] string @namespace, [NotNull] string className)
        {
            if (@namespace == null) throw new ArgumentNullException(nameof(@namespace));
            if (className == null) throw new ArgumentNullException(nameof(className));

            var classDeclaration = SyntaxFactory.ClassDeclaration(className).AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
            var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(@namespace)).NormalizeWhitespace();
            namespaceDeclaration = namespaceDeclaration.AddMembers(classDeclaration);
            return namespaceDeclaration.NormalizeWhitespace().ToFullString();
        }

组装准备代码:

blic static void GenerateAssembly([NotNull] this string sourceCode, [NotNull] string assemblyFilePath,
            [NotNull] params string[] referencedAssemblyPaths)
        {
            if (sourceCode == null) throw new ArgumentNullException(nameof(sourceCode));
            if (assemblyFilePath == null) throw new ArgumentNullException(nameof(assemblyFilePath));

            var assemblyFileName = Path.GetFileName(assemblyFilePath);
            var outputDirectory = Path.GetDirectoryName(assemblyFilePath);
            Directory.CreateDirectory(outputDirectory);

            var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
            var referencedAssemblyMetadata =
                referencedAssemblyPaths.Select(x => MetadataReference.CreateFromFile(x).WithProperties(new MetadataReferenceProperties()));
            var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
            var compilation = CSharpCompilation.Create(assemblyFileName, new[] {syntaxTree}, referencedAssemblyMetadata, compilationOptions);

            using (var fs = File.Create(assemblyFilePath))
            {
                var emitResult = compilation.Emit(fs);
                if (!emitResult.Success)
                {
                    var failures = emitResult.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error);
                    var errorReport = failures.Select(x => $"{x.Id}: {x.GetMessage()}, {x.Location}");
                    throw new InvalidOperationException($"Failed to compile source code {sourceCode}. Report: {errorReport}");
                }

                fs.Flush();
            }
        }

为简单起见,我想生成两个程序集:

  • 唯一依赖于 netstandard.dll 的 B
  • A 同时引用了 netstandard.dll 和 B

代码如下:

  var emptyClassSourceCode = RoslynAssemblyGenerator.GenerateEmptyPublicClass("DummyNamespace", "DummyClass");
            var standardAssemblyLocation = Path.Combine(Path.GetDirectoryName(Common.ExecutingAssemblyFullPath), "Resources", "netstandard.dll");

            // A references B
            var aPath = Path.Combine(AssemblyGenerationPath, "A.dll");
            var bPath = Path.Combine(AssemblyGenerationPath, "B.dll");
            emptyClassSourceCode.GenerateAssembly(bPath, standardAssemblyLocation);
            emptyClassSourceCode.GenerateAssembly(aPath, bPath, standardAssemblyLocation);

B按预期生成,但是A没有引用B:

无法弄清楚我错过了什么,为什么 A 没有引用 B。

【问题讨论】:

  • 我看不到您的程序集 A 引用 B 的位置。它只有空类,没有引用 B 中的任何内容。
  • referencedAssemblyMetadata 是从目标程序集的路径创建的,然后作为第三个参数传递给编译。我认为当我将程序集元数据传递给编译时,程序集作为参考添加。我错了吗?
  • 您只需将路径传递给程序集以查找元数据,但如果您不使用其中的任何元数据,为什么要添加它们作为参考?
  • 是的,没错。我已将代码更改为发出方法,该方法只需从不同的程序集创建一个类的实例并得到预期的结果:A 引用了 B。谢谢!
  • 据我了解,在这种情况下,我必须从程序集 A 中引用程序集 B。 例如,这如何与插件系统一起工作?主应用程序应该显式引用所有插件的程序集(其中一些在构建主应用程序时可能还不存在)?如果是这样,那就太局限了,不实用。

标签: c# code-generation roslyn


【解决方案1】:

正如评论中提到的 PetSerAl,为了引用程序集,我们不仅需要指明程序集位置,还需要实际使用它的元数据。

【讨论】:

  • 我没有看到任何来自 PetSerAl 的 cmets。他们被移除了吗?答案是什么?我也遇到了这个问题。
  • 从 user4003407 读取 cmets。您不仅应该指定查找其他程序集的位置,还应该在代码中实际使用其他程序集的元数据。
猜你喜欢
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 2016-09-30
  • 2016-03-16
  • 2014-02-03
  • 2012-03-11
  • 2013-09-07
相关资源
最近更新 更多