You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Blazor共享项目的C#源代码生成器访问服务端编译上下文?

解决Blazor Shared项目源码生成器访问服务端编译上下文的简洁方案

你遇到的这个问题在Blazor全栈开发里挺常见——想通过源码生成器自动把WebAPI的特性路由转成Shared项目里的URL生成方法,但Shared项目的生成器拿不到服务端的路由特性信息,硬编码解决方案路径又不够优雅。下面给你几个简洁的解决思路:

方案1:独立源码生成器项目 + 输出到Shared目录

这是最推荐的方案,既让生成器能访问服务端的编译上下文,又能让生成的代码自动进入Shared项目供两端使用:

  1. 创建独立的源码生成器类库:别把生成器放在Shared项目里,单独新建一个类库项目(比如YourApp.ApiRouteGenerator),引用Roslyn必要包(Microsoft.CodeAnalysis.CSharp、Microsoft.CodeAnalysis.Analyzers等)。
  2. 服务端项目引用生成器并配置输出:在WebAPI项目的.csproj里添加对生成器项目的引用,同时指定生成代码的输出目录为Shared项目的某个文件夹:
<ItemGroup>
  <ProjectReference Include="..\YourApp.ApiRouteGenerator\YourApp.ApiRouteGenerator.csproj"
                    OutputItemType="Analyzer"
                    ReferenceOutputAssembly="false" />
</ItemGroup>
<PropertyGroup>
  <!-- 把生成的代码输出到Shared项目的Generated文件夹,确保Shared项目包含这个目录 -->
  <GeneratedOutputDirectory>..\YourApp.Shared\Generated</GeneratedOutputDirectory>
</PropertyGroup>
  1. 生成器逻辑与Shared项目配置:生成器里可以正常读取服务端项目的[Route]、[HttpGet]等特性,生成URL方法后写入指定输出路径。最后在Shared项目的.csproj里添加<Compile Include="Generated/**/*.cs" />,让Shared自动包含生成的代码,客户端和服务端就能直接调用这些URL生成方法了。

这个方案完全利用Roslyn原生的编译上下文,不需要额外加载解决方案,既能保证生成逻辑的准确性,又能实现代码的跨端共享。

方案2:服务端+Shared共享路由常量(无生成器折中方案)

如果不想折腾独立生成器项目,这个手动维护的方案也能解决问题,适合路由变动不频繁的场景:

  1. 在Shared项目定义路由常量:创建一个静态类存储所有路由规则和名称:
public static class ApiRouteConstants
{
    public const string ClientByIdRoute = "api/clients/{id}";
    public const string ClientRouteName = "Client";
}
  1. 服务端引用常量配置路由:WebAPI的特性路由直接使用Shared里的常量:
[HttpGet]
[Route(ApiRouteConstants.ClientByIdRoute, Name = ApiRouteConstants.ClientRouteName)]
public async Task<ClientViewModel> GetById(int id)
{
    var client = await _clientLogic.GetById(id);
    return _clientViewLogic.ToViewModel(client);
}
  1. Shared里编写URL生成方法:基于同一个常量类实现URL拼接:
public static string GetClientUrl(string id)
{
    return ApiRouteConstants.ClientByIdRoute.Replace("{id}", id);
}

这种方式不需要生成器,通过共享常量保证路由规则的一致性,手动维护成本低。

方案3:通过MSBuild属性传递解决方案路径(不推荐,相对复杂)

如果坚持要用Shared项目里的生成器,可以通过MSBuild把解决方案路径传递给生成器,避免硬编码:

  1. 服务端项目传递路径:在WebAPI项目的.csproj里添加:
<PropertyGroup>
  <SolutionPath>$(SolutionDir)</SolutionPath>
</PropertyGroup>
  1. 生成器获取路径并加载工作区:在生成器里通过上下文获取路径,加载解决方案:
public void Execute(GeneratorExecutionContext context)
{
    if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.SolutionPath", out var solutionPath))
    {
        var workspace = MSBuildWorkspace.Create();
        var solution = workspace.OpenSolutionAsync(solutionPath).Result;
        // 遍历服务端项目的编译单元,获取路由特性信息
    }
}

不过这个方案需要处理异步加载的异常情况,实现复杂度高,除非有特殊需求不推荐使用。


内容的提问来源于stack exchange,提问作者cpaulus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:24:41