C# 从生成的源中触发源生成器

问题描述 投票:0回答:1

我创建了一个增量源生成器,它生成一个满足 JSON 源生成器类要求的类。

我的问题是:如何从源生成文件触发源生成?目前我已经通过两次构建项目解决了这个问题。第一次它会执行我的生成器并失败('WeatherJsonContext' 没有实现继承的抽象成员......)。第二次它将执行 JSON 源生成器并且构建成功。

一些代码(为了测试,我使用 const):

namespace ClassJsonGen;

using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

[Generator]
public class CustomGenerator : IIncrementalGenerator
{
    private const string TestSource = @"
            namespace WebJsonGen {
                using System.Text.Json.Serialization;
                [JsonSerializable(typeof(IEnumerable<WeatherForecast>))]
                [JsonSerializable(typeof(IEnumerable<StormForecast>))]
                public partial class WeatherJsonContext : JsonSerializerContext
                { } 
            }";

    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
#if DEBUG
        if (!Debugger.IsAttached)
        {
            Debugger.Launch();
        }
#endif

        var todoInput = context.SyntaxProvider
            .CreateSyntaxProvider(
                predicate: static (s, _) => s is ClassDeclarationSyntax,
                transform: static (ctx, _) => ctx.Node)
            .Where(static m => m is not null);

        context.RegisterSourceOutput(todoInput, (ctx, inp) =>
        {
            // TODO use input to determine which [JsonSerializable] we need :-)
            ctx.AddSource("JSON.g.cs", SourceText.From(TestSource, Encoding.UTF8));
        });
    }
}

产生:

namespace WebJsonGen {
    using System.Text.Json.Serialization;
    [JsonSerializable(typeof(IEnumerable<WeatherForecast>))]
    [JsonSerializable(typeof(IEnumerable<StormForecast>))]
    public partial class WeatherJsonContext : JsonSerializerContext
    { } 
}

在我在 .csproj 中添加的消费项目中:

    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>

    <ItemGroup>
        <!-- Exclude the output of source generators from the compilation -->
        <Compile Remove="$(CompilerGeneratedFilesOutputPath)/System.Text.Json.SourceGeneration/**/*.cs" />
        <Compile Include="$(CompilerGeneratedFilesOutputPath)/System.Text.Json.SourceGeneration/**/JSON*.cs" />
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\ClassJsonGen\ClassJsonGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
    </ItemGroup>
c# .net code-generation
1个回答
0
投票

不是在代码中硬编码源代码,
您可以在您的项目中使用

T4 templates
代码生成和 T4 模板

  1. 在解决方案资源管理器中,在项目的快捷菜单上,选择
    Add > New Item
  2. Add New Item
    对话框中,选择
    Runtime Text Template
    Text Template
    。 (在 Visual Basic 中查看
    Common Items > General
    。)

样板:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>

namespace WebJsonGen
{
    using System.Text.Json.Serialization;
    [JsonSerializable(typeof(IEnumerable<WeatherForecast>))]
    [JsonSerializable(typeof(IEnumerable<StormForecast>))]
    public partial class WeatherJsonContext : JsonSerializerContext
    { }
}

当您保存 .tt 文件时,会生成一个附属文件,其扩展名是您在

<#@ output extension=".cs" #>
预处理器中指定的。 您还可以在运行时生成辅助文件

© www.soinside.com 2019 - 2024. All rights reserved.