在VS Code中,如何在设计时根据JSON文件自动生成一个.cs文件,而不需要手动构建?

编程语言 2026-07-08

我在模块根目录有一个permissions.json文件,它是权限常量的唯一权威来源。我想要一个Permissions.g.cs文件在我保存JSON的瞬间自动重新生成,这样IDE的 C# IntelliSense就能即时更新,无需触发构建。

我当前有一个Roslyn增量源生成器 (IIncrementalGenerator),通过 <AdditionalFiles> 连接,在构建时能正确生成该类。问题在于它只在编译时运行,而IntelliSense只有在发生 dotnet build 之后才会反映更改,这打乱了工作流程。

我的JSON结构:

{
  "Catalog": {
    "Access": "catalog.access",
    "Items": {
      "View": "catalog.items.view",
      "Add": "catalog.items.add"
    }
  }
}

期望的生成输出:

public static partial class Permissions
{
    public static class Catalog
    {
        public const string Access = "catalog.access";
        public static class Items
        {
            public const string View = "catalog.items.view";
            public const string Add = "catalog.items.add";
        }
    }
}

我想要的效果: 编辑 permissions.jsonPermissions.g.cs,磁盘上的更新能即时生效 → IDE的 IntelliSense即时刷新——且没有手动构建,也不需要启动任何外部进程。

是否存在一个官方自带的机制,能够在.NET项目中从JSON文件实现真正的设计时 .cs 生成,而无需安装第三方软件包或扩展,并且在VS Code中也能工作?

解决方案

你增量生成器只在完全构建时更新的原因,是通过 <AdditionalFiles> 包含的文件不会被IDE的后台编译器(Roslyn LSP)视为“实时”或会改变状态的输入。为了在你保存JSON文件的瞬间实现即时的IntelliSense更新,你需要做两件事:

  1. 使用更新后的 context.AdditionalFilesProvider,并结合 AnalyzerAdditionalFileProvider,在源生成器中动态检测文件修改。
  2. 配置你的 .csproj,让Visual Studio/OmniSharp主动监视这个JSON文件。

下面是修改你的设置以实现保存时实时生成的方法。

1.更新源生成器代码

不要只是以传统方式读取附加文件,而要确保你在使用 AdditionalFilesProvider 流水线并监控 SourceText 的变化。

下面是你应该如何构建你的 Initialize 方法,以确保在保存文件时IDE能更新生成器缓存:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using System.IO;
using System.Linq;

[Generator]
public class PermissionGenerator : IIncrementalGenerator
{
    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        // 1. Filter for your permissions.json file
        IncrementalValuesProvider<AdditionalText> jsonFiles = context.AdditionalFilesProvider
            .Where(file => Path.GetFileName(file.Path).Equals("permissions.json", System.StringComparison.OrdinalIgnoreCase));

        // 2. Extract the text content and path as a combined model
        IncrementalValuesProvider<(string Path, SourceText Content)> jsonContents = jsonFiles
            .Select((file, cancellationToken) => 
            {
                var text = file.GetText(cancellationToken);
                return (Path: file.Path, Content: text);
            })
            // Crucial: Only proceed if content actually changed
            .Where(x => x.Content != null); 

        // 3. Register the source output
        context.RegisterSourceOutput(jsonContents, (spc, source) =>
        {
            string jsonRawText = source.Content.ToString();

            // Your custom JSON parsing logic here 
            // string generatedCode = ParseAndGenerate(jsonRawText);

            // Dummy representation of your expected output
            string generatedCode = @"
public static partial class Permissions
{
    public static class Catalog
    {
        public const string Access = ""catalog.access"";
        public static class Items
        {
            public const string View = ""catalog.items.view"";
            public const string Add = ""catalog.items.add"";
        }
    }
}";

            spc.AddSource("Permissions.g.cs", SourceText.From(generatedCode, System.Text.Encoding.UTF8));
        });
    }
}

2.更新你的 .csproj(秘密配方)

为了让IDE在保存非代码文件时即时触发后台生成器,你必须明确声明元数据,强制项目系统对其进行监视。

更新你所消费的项目的 .csproj 文件,加入以下具体属性:

<ItemGroup>
  <AdditionalFiles Include="permissions.json" Link="permissions.json">
    <CopyToOutputDirectory>Never</CopyToOutputDirectory>
  </AdditionalFiles>

  <CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="FullPath" />
</ItemGroup>

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

3. IDE即时更新清单

如果在这些改动后仍未立即更新,请检查以下环境问题:

  • Visual Studio / Rider重启:当你改变一个 IIncrementalGenerator 自身的体系结构时,IDE会积极缓存旧的DLL。修改并重新构建Generator项目后,必须重启IDE。
  • 属性跟踪:<CompilerVisibleItemMetadata> 标签充当钩子,告诉IDE的实时工作区引擎:如果这个文件被修改并保存,就会使与之相关的生成器缓存节点失效。这正是让IntelliSense在不手动构建的情况下点亮的原因。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章