增量源代码生成器在间接关联项目中运行的问题及解决方法
问题原因及解决方案
原因分析
- NuGet的依赖传递特性:当你在"Models"项目中引用源代码生成器NuGet包时,所有引用"Models"的其他项目会自动继承这个包作为间接依赖,NuGet默认会传递所有依赖项到下游项目。
- 增量源代码生成器的编译时加载机制:生成器属于编译阶段的组件,只要项目的依赖链中存在生成器包,Roslyn编译引擎就会在该项目编译时加载并执行生成器,不管引用是直接还是间接的。
阻止生成器在间接引用项目中运行的方法
1. 限制NuGet包的依赖传递性
在"Models"项目的.csproj文件中,修改生成器包的引用配置,添加PrivateAssets="all"属性,将该包的所有资产标记为仅当前项目可用,不会传递到下游项目:
<PackageReference Include="你的生成器包名称" Version="对应版本号" PrivateAssets="all" />
2. 在生成器代码中添加项目过滤逻辑
在生成器的Initialize方法里添加判断逻辑,仅在目标项目(如"Models"项目)中执行生成操作。可以通过检查项目的程序集名称来过滤:
using Microsoft.CodeAnalysis; [Generator] public class YourIncrementalGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { // 仅允许程序集名称包含"Models"的项目触发生成逻辑 var shouldRunGenerator = context.CompilationProvider .Select((compilation, _) => compilation.AssemblyName.Name?.Contains("Models", StringComparison.OrdinalIgnoreCase) ?? false); // 基于过滤条件构建生成管道 var generatorPipeline = shouldRunGenerator .Where(shouldRun => shouldRun) // 后续添加你的生成逻辑代码... ; // 注册生成输出(示例) // context.RegisterSourceOutput(generatorPipeline, (ctx, _) => { /* 生成代码逻辑 */ }); } }
3. 调整NuGet包的打包配置
如果你是生成器NuGet包的构建者,可以修改打包路径:将生成器组件从buildTransitive目录改为build目录。buildTransitive下的组件会被间接引用的项目加载,而build目录下的组件仅对直接引用的项目生效。
在生成器项目的.csproj中修改打包配置:
<ItemGroup> <!-- 替换原有的buildTransitive配置 --> <None Include="$(OutputPath)你的生成器程序集.dll" Pack="true" PackagePath="build" /> <!-- 同步将配套的.props/.targets文件打包到build目录 --> <None Include="build\你的生成器.props" Pack="true" PackagePath="build" /> </ItemGroup>
内容的提问来源于stack exchange,提问作者George Fabish
相关产品推荐
相关产品推荐

