【问题标题】:Is there a method or a way in Roslyn to enumerate all assemblies used at compile time by a given C# projectRoslyn 中是否有方法或方式来枚举给定 C# 项目在编译时使用的所有程序集
【发布时间】:2020-09-09 22:15:23
【问题描述】:

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

【问题讨论】:

    标签: c# assemblies roslyn roslyn-code-analysis external-assemblies


    【解决方案1】:

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

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

    引用的程序集

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

      <ItemGroup>
        <ProjectReference Include="..\Common\Common.csproj" />
      </ItemGroup>
    
      <ItemGroup>
        <PackageReference Include="MessagePack" Version="2.1.115" />
      </ItemGroup>
    

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

    更新

    为了收集transitive dependencies,还有几个选项。

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

    • 如果您想避免恢复项目/解决方案,您可以从.csproj 中找到的包开始,如上所述,并使用NuGet Server API 获取每个依赖项的数组。递归执行此操作将产生与dotnet restore 相同的结果。 NuGet Core 将 API 包装为 C# 类,因此您可以直接从代码中调用它。可以在这里轻松查询依赖关系:How to get the dependencies of a NuGet package from private NuGet feed?

    必需的程序集

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

    Roslyn 语义模型

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

    IL 选项

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

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

    加载选项

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

    【讨论】:

    • 感谢@Isolin 的回答,但这种方法不会处理传递依赖关系。
    • 嗨@Tahatoun,您认为在引用集或所需集中会出现问题吗?你能给我一个不能识别传递引用的例子吗?我真的很想知道并可能解决我的方法。
    • 在 .Net Core 项目传递依赖项在还原期间由 nuget 管理。这将是一个被引用的问题,例如,如果项目引用了一个包 A,而后者又引用了一个包 B。包 B 不会出现在项目文件文件中
    • 我明白了,这是真的。您可以致电dotnet restore 收集所有引用的包吗?不幸的是,restore 命令没有试运行
    猜你喜欢
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多