Roslyn Analyzer/Source Generator中如何区分直接与传递程序集引用?
问题结论与实现方案
首先明确基础结论:
传递引用属于MSBuild层面的特性,和Roslyn编译器逻辑无关。编译器仅能拿到MSBuild最终传递过来的全量程序集引用集合,不保留引用来源链路,因此直接基于
CodeAnalysis.Compilation对象没有内置方法可以区分直接引用与传递引用,Compilation.References、Compilation.ReferencedAssemblyNames返回的均是包含两种引用类型的全量集合,和你现有的认知一致。
区分两种引用的可行方案
你提到的通过MSBuild提取信息的思路是可行的,但不要尝试在分析器/源代码生成器运行时直接访问MSBuild Project对象(Roslyn上下文和MSBuild上下文相互隔离,没有直接访问入口),正确实现逻辑如下:
- 第一步:在分析器/生成器关联的MSBuild props/targets文件中,预计算当前项目的直接引用集合,包括直接添加的
AssemblyReference、直接ProjectReference对应的输出程序集、直接PackageReference包含的程序集,将集合拼接为用分隔符分隔的字符串。 - 第二步:通过MSBuild的
CompilerVisibleProperty配置项,将上述拼接好的字符串标记为编译器可见的全局属性,传递到Roslyn上下文。 - 第三步:在分析器/生成器的初始化方法中读取该全局属性,解析得到直接引用列表,再和
Compilation.References中的项做匹配,即可区分直接与传递引用。
实现注意事项
- 该方案需要你可以向使用分析器/生成器的项目注入MSBuild配置,如果是公开发布的分析器,需要将对应的props文件嵌入到NuGet包中,安装时自动导入到目标项目。
- 匹配引用时建议使用程序集强名称(含版本、公钥Token)作为匹配依据,避免同名程序集导致的误判。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

