我正在开发一个应用程序,该程序可以检测并消除给定C#项目中无用的外部引用,例如引用但未使用的包。为此,我需要枚举在编译和运行时使用的所有程序集。对于在运行时使用的变量,我可以使用反射专门调用Assembly.GetReferencedAssemblies()
来获得名称。但是对于仅在编译时使用的那些,我认为如果不使用Roslyn,就无法列出它们。您能不能解决我遇到的问题?
Roslyn中是否有方法或方法枚举给定C#项目在编译时使用的所有程序集 更新罗斯林语义模型 IL选项加载选项
iCMS 回答:Roslyn中是否有方法或方法枚举给定C#项目在编译时使用的所有程序集 更新罗斯林语义模型 IL选项加载选项
这只是一种简单的方法,远非完美。我相信您可以根据自己的需要去加深与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 getting dependencies for class
IL选项
您可以使用Roslyn编译给定的项目,然后加载生成的IL并查找诸如[System.Private.CoreLib]
之类的引用。只需将所有引用的程序集放入HashSet
中,然后在IL中找到匹配的调用,即可将其删除。结果集将包含可以删除的引用。
也许this project可以帮助查看IL。另外,当您需要罗斯林输出示例时,SharpLab也非常方便。
加载选项
如果可以很好地加载已编译的项目,则可以按照问题中的说明使用Assembly.GetReferencedAssemblies()
而不用分析IL。