我正在开发一个应用程序,它可以检测并消除给定C#项目中的无用外部引用,例如一个被引用但未使用的包。为此,我需要枚举所有在编译和运行时使用的程序集。对于那些在运行时使用的程序集,我可以使用反射来获取名称,特别是调用 Assembly.GetReferencedAssemblies()
. 但对于那些只在编译时使用的,我认为没有办法在不使用Roslyn的情况下列出它们。请你回答我的问题。
这只是一个简单的方法,远非完美。我相信你可以更深入地了解Roslyn,并根据自己的需要尽情地玩耍。我也相信在编译器和Roslyn方面有比我更优秀的专家 :)
请注意,这种方法不能处理动态加载的程序集。它可以避免运行项目。
您可以使用XML解析器代替Roslyn来分析项目或解决方案文件。在那里你会发现所有被引用的包和项目的列表,例如:.NET Core 3.1。
<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和运行时包。
如果你想避免恢复projectsolution,你可以从在 .csproj
如上所述,并使用 NuGet服务器API 来获取每个依赖关系的数组。递归地这样做会得到与 dotnet restore
. NuGet核心 将API包装成C#类,所以你可以直接从你的代码中调用它。依赖关系可以像这里一样轻松查询。如何从私有的NuGet feed中获取NuGet包的依赖关系?
现在你需要确定那些真正需要的东西。编译过程会处理这些问题。它不会(据我所知)在编译后的代码中插入任何不必要的引用。
在这个问题中解决了。Roslyn获取类的依赖关系
您可以使用Roslyn编译给定的项目,然后加载生成的IL,并查找引用,如 [System.Private.CoreLib]
. 只需将所有引用的装配体扔进一个 HashSet
并在IL中找到匹配的调用后删除它们。由此产生的集合将包含可以被删除的引用。
也许 本项目 可以帮助查看IL。同时 夏普实验室 当您需要Roslyn输出示例时,可以非常方便地使用。
如果你对加载编译后的项目没有意见,你可以使用 Assembly.GetReferencedAssemblies()
如你在问题中指出的,而不是分析IL。