如何通过Roslyn从控制器路由生成可被下游项目调用的代码?
解决方案
一、正确配置源生成器的项目引用
源生成器不能用普通项目引用,必须以分析器引用的方式添加到包含控制器的启动项目(即你的API/Server项目):
- 在启动项目的
.csproj中添加以下配置:
这样生成器才能在启动项目编译时扫描控制器代码并生成路由类。<ItemGroup> <ProjectReference Include="..\Path\To\Your\Generator\Project.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup>
二、修正命名空间生成逻辑
你设置的命名空间未生效,大概率是生成器获取目标命名空间的方式有误:
- 不要硬编码命名空间,而是从目标项目的默认命名空间或者指定的共享项目命名空间获取。可以通过生成器上下文的
Compilation对象获取:// 在源生成器的 Execute 方法中获取目标项目的默认命名空间 var defaultNamespace = compilation.AssemblyName.Name ?? "OurGov.Data.Shared.Models.Routes"; // 用这个命名空间生成代码 - 或者在启动项目的
.csproj中添加自定义属性,让生成器读取:
然后在生成器中通过<PropertyGroup> <ApiRoutesNamespace>OurGov.Data.Shared.Models.Routes</ApiRoutesNamespace> </PropertyGroup>context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.ApiRoutesNamespace", out var namespaceValue)获取并使用。
三、让下游项目自动访问生成的代码
根据你的项目架构(Server → Shared → Client),需要让生成的路由类能被Shared项目引用,进而被Client项目使用:
将生成的代码输出到Shared项目目录:
在启动项目的.csproj中配置生成器的输出路径,指向Shared项目的某个目录(比如Models/Routes):<PropertyGroup> <GeneratedRoutesOutputPath>..\OurGov.Data.Shared\Models\Routes</GeneratedRoutesOutputPath> </PropertyGroup>然后在生成器中读取这个路径,将生成的
.cs文件写入该目录。这样Shared项目会自动包含这些生成的代码,下游Client项目引用Shared后就能直接使用。或者使用共享的代码生成目录:
配置启动项目将生成的代码输出到一个双方都能访问的目录,然后在Shared项目中添加对该目录的文件引用:<!-- 在Shared项目的.csproj中 --> <ItemGroup> <Compile Include="..\Generated\ApiRoutes\**\*.cs" Link="Models/Routes/%(Filename)%(Extension)" /> </ItemGroup>验证依赖传递:
确保生成的代码是无依赖的纯静态类(就像你示例中仅返回字符串路由的形式),这样下游项目不需要额外引用启动项目;如果生成代码依赖控制器相关特性,需确保Shared项目正确引用对应依赖。
四、额外验证步骤
- 清理并重建整个解决方案,确保生成器触发并生成了正确的代码文件。
- 检查生成的代码文件的命名空间是否与Shared项目的命名空间一致,且文件被正确包含在Shared项目中。
- 在Client项目中尝试引用
OurGov.Data.Shared.Models.Routes.ApiRoutes,确认能否正常识别。
内容的提问来源于stack exchange,提问作者Taylor C. White
相关产品推荐
相关产品推荐

