partial class Program
{
[GeneratedRegex("abc|def", RegexOptions.IgnoreCase)]
private static partial Regex AbcOrDefGeneratedRegex();
}
2. 正则表达式的生成结果
复制代码
partial class Program
{
/// <remarks>
/// Pattern:<br/>
/// <code>abc|def</code><br/>
/// Options:<br/>
/// <code>RegexOptions.IgnoreCase</code><br/>
/// Explanation:<br/>
/// <code>
/// ○ Match with 2 alternative expressions, atomically.<br/>
/// ○ Match a sequence of expressions.<br/>
/// ○ Match a character in the set [Aa].<br/>
/// ○ Match a character in the set [Bb].<br/>
/// ○ Match a character in the set [Cc].<br/>
/// ○ Match a sequence of expressions.<br/>
/// ○ Match a character in the set [Dd].<br/>
/// ○ Match a character in the set [Ee].<br/>
/// ○ Match a character in the set [Ff].<br/>
/// </code>
/// </remarks>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "8.0.14.7010")]
private static partial global::System.Text.RegularExpressions.Regex AbcOrDefGeneratedRegex()
=> global::System.Text.RegularExpressions.Generated.AbcOrDefGeneratedRegex_0.Instance;
// ...
}
class HelloGenerator()
: ValuesGenerator<HelloSource>(
"GenerateCoreTests.Hello.HelloGeneratorAttribute",
new SyntaxFilter(true, SyntaxKind.ClassDeclaration),
new HelloTransform(),
new GeneratorExecutor<HelloSource>())
{
}
class HelloTransform : IGeneratorTransform<HelloSource>
{
public HelloSource? Transform(GeneratorAttributeSyntaxContext context, CancellationToken cancellation)
{
if (context.TargetNode is ClassDeclarationSyntax type && context.TargetSymbol is INamedTypeSymbol symbol)
return new(type, symbol);
return null;
}
}
4. HelloSource是比较纯净的业务逻辑
复制代码
class HelloSource(ClassDeclarationSyntax type, INamedTypeSymbol symbol)
: IGeneratorSource
{
private readonly ClassDeclarationSyntax _type = type;
private readonly INamedTypeSymbol _symbol = symbol;
string GenerateFileName
=> $"{_symbol.ToDisplayString()}.Hello.g.cs";
public SyntaxGenerator Generate()
{
var builder = SyntaxGenerator.Clone(_type);
var method = GenerateMethod();
builder.AddMember(method);
return builder;
}
public static MethodDeclarationSyntax GenerateMethod()
{
var name = SyntaxFactory.IdentifierName("name");
var expression = SyntaxGenerator.Interpolation()
.Add("Hello: '")
.Add(name)
.Add("'")
.Build();
return SyntaxGenerator.VoidType.Method("SayHello", SyntaxGenerator.StringType.Parameter(name.Identifier))
.Public()
.Static()
.ToBuilder()
.Add(SyntaxFactory.IdentifierName("Console").Access("WriteLine").Invocation([expression]))
.End();
}
}
5. 测试代码如下
复制代码
namespace GenerateCoreTests.Hello;
[HelloGenerator]
public partial class HelloTests;
6. 生成代码如下
复制代码
// <auto-generated/>
namespace GenerateCoreTests.Hello;
partial class HelloTests
{
public static void SayHello(string name)
{
Console.WriteLine($"Hello: '{name}'");
}
}
var source = "partial class Greeting;";
var service = SyntaxTreeScript.Create()
.Using("System");
var result = service.Generate<HelloGenerator>(source)
.GetRunResult();
var tree = result.GeneratedTrees.FirstOrDefault();
Assert.NotNull(tree);
var diagnostics = result.Diagnostics;
Assert.Empty(diagnostics);
3.2 SyntaxScripting添加引用
通过Reference增加该类的程序集为引用
复制代码
var service = SyntaxTreeScript.Create()
.Reference<DateTime>();
var source = "partial class Greeting;";
var result = SyntaxScripting.Default.Generate<HelloGenerator>(source)
.GetRunResult();
var tree = result.GeneratedTrees.FirstOrDefault();
Assert.NotNull(tree);
var diagnostics = result.Diagnostics;
Assert.Empty(diagnostics);
3.4 CreateDefault
同Default一样using System并引用CurrentDomain的所有程序集
不同之处是非共享,每次调用CreateDefault都是新实例
复制代码
var source = "partial class Greeting;";
var result = SyntaxScripting.CreateDefault()
.Generate<HelloGenerator>(source)
.GetRunResult();
var tree = result.GeneratedTrees.FirstOrDefault();
Assert.NotNull(tree);
var diagnostics = result.Diagnostics;
Assert.Empty(diagnostics);
var code0 = @"
namespace GenerateCoreTests.Hello;
[HelloGenerator]
partial class HelloTests;
";
var compilation = SyntaxTreeScript.Default
.Compile(code0);
var syntaxTree = compilation.SyntaxTrees.FirstOrDefault();
Assert.NotNull(syntaxTree);
var type = syntaxTree.GetRoot()
.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault();
Assert.NotNull(type);
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var symbol = semanticModel.GetDeclaredSymbol(type);
Assert.NotNull(symbol);
HelloSource source = new(type, symbol);
var builder = source.Generate();
var code = builder.Build()
.WithGenerated()
.ToFullString();
Assert.Contains("SayHello", code);