Рослин, похоже, игнорирует некоторые ссылки на метаданные - PullRequest
1 голос
/ 28 сентября 2019

На этапе подготовки некоторых интеграционных тестов мне нужно динамически генерировать некоторые сборки со ссылками на другие сборки и записывать их на диск.Я полагаю, очевидным выбором для этой задачи является Рослин.Компиляция 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();
            }
        }

Для простоты я хочу создать две сборки:

  • B с единственной зависимостью от netstandard.dll
  • 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:

enter image description here

Не могу понять, что я пропустил, почему на А не ссылается А.

1 Ответ

0 голосов
/ 29 сентября 2019

Как упомянул PetSerAl в комментарии, для ссылки на сборку нам нужно не только указать место сборки, но и фактически использовать ее метаданные.

...