我创建了一个增量源生成器,它生成一个满足 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>
不是在代码中硬编码源代码,
您可以在您的项目中使用
T4 templates
。
代码生成和 T4 模板
Add > New Item
。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" #>
预处理器中指定的。
您还可以在运行时生成辅助文件