0

我正在开发一个应用程序,用于检测并消除给定 C# 项目中无用的外部引用,例如引用但未使用的包。为此,我需要枚举在编译和运行时使用的所有程序集。对于那些在运行时使用的,我可以使用反射专门调用Assembly.GetReferencedAssemblies(). 但是对于那些仅在编译时使用的,我认为没有使用 Roslyn 就无法列出它们。请问您对我的问题有任何答案吗?

4

1 回答 1

0

这只是一种简单的方法,远非完美。我相信你可以更深入地和 Roslyn 一起玩。我也确信那里有比我更好的编译器和 Roslyn 专家:)

请注意,此方法不处理动态加载的程序集。它避免了运行项目。

引用的程序集

您可以使用 XML 解析器而不是 Roslyn 来分析项目或解决方案文件。在那里你会找到所有引用的包和项目的列表,例如:

  <ItemGroup>
    <ProjectReference Include="..\Common\Common.csproj" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="MessagePack" Version="2.1.115" />
  </ItemGroup>

上面的示例来自一个 .NET Core 3.1 项目文件。

更新

为了收集传递依赖,还有几个选项。

  • 对于 .NET Core 项目,您可以调用dotnet restore并阅读以下文件$ProjectFolder/obj/project.assets.json。它是一个 json 文件,其中包含已解析的所有引用,其中包含 NuGet 和运行时包。

  • 如果您想避免恢复项目/解决方案,您可以从.csproj如上所述找到的包开始,并使用NuGet Server API获取每个依赖项的数组。递归执行此操作将产生与 相同的结果dotnet restoreNuGet Core将 API 包装为 C# 类,因此您可以直接从代码中调用它。可以像这里一样轻松查询依赖项:如何从私有 NuGet 源获取 NuGet 包的依赖项?

所需的组件

现在你需要确定那些真正需要的。编译过程会处理这个问题。它不会(据我所知)在编译的代码中插入任何不必要的引用。

Roslyn 语义模型

在这个问题中解决:Roslyn getting dependencies for class

IL 选项

您可以使用 Roslyn 编译给定项目,然后加载生成的 IL 并查找类似[System.Private.CoreLib]. HashSet一旦在 IL 中找到匹配的调用,只需将所有引用的程序集放入 a并删除它们。结果集将包含可以删除的引用。

也许这个项目可以帮助查看 IL。当您需要 Roslyn 输出示例时,SharpLab也非常方便。

加载选项

如果您可以加载已编译的项目,则可以Assembly.GetReferencedAssemblies()按照问题中的指示使用,而不是分析 IL。

于 2020-05-23T01:10:01.063 回答