前言
Source Generators
顾名思义代码生成器,可进行创建编译时代码,也就是所谓的编译时元编程
,这可让一些运行时映射的代码改为编译时,同样也加快了速度,我们可避免那种昂贵的开销,这是有价值的。
实现ISourceGenerator
集成ISourceGenerator
接口,实现接口用于代码生成策略,它的生命周期由编译器控制,它可以在编译时创建时创建并且添加到编译中的代码,它为我们提供了编译时元编程,从而使我们对C#代码或者非C#源文件进行内部的检查。
[Generator] class CustomGenerator: ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { throw new NotImplementedException(); } public void Execute(GeneratorExecutionContext context) { throw new NotImplementedException(); } }
public void Execute(GeneratorExecutionContext context){ var compilation = context.Compilation; var simpleCustomInterfaceSymbol = compilation.GetTypeByMetadataName("SourceGeneratorDemo.ICustom"); const string code = @"using System;namespace SourceGeneratorDemo{ public partial class Program{ public static void Display(){ Console.WriteLine(""Hello World!""); } }}"; if (!(context.SyntaxReceiver is CustomSyntaxReceiver receiver)) return; //语法树可参考Roslyn Docs SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code); //context.AddSource("a.class", code); context.AddSource("a.class", SourceText.From(text: code, encoding: Encoding.UTF8)); //https://github.com/gfoidl-Tests/SourceGeneratorTest { StringBuilder sb = new(); sb.Append(@"using System;using System.Runtime.CompilerServices;#nullable enable[CompilerGenerated]public static class ExportDumper{ public static void Dump() {"); foreach (BaseTypeDeclarationSyntax tds in receiver.Syntaxes) { sb.Append($@" Console.WriteLine(""type: {GetType(tds)}\tname: {tds.Identifier}\tfile: {Path.GetFileName(tds.SyntaxTree.FilePath)}"");"); } sb.AppendLine(@" }}"); SourceText sourceText = SourceText.From(sb.ToString(), Encoding.UTF8); context.AddSource("DumpExports.generated", sourceText); static string GetType(BaseTypeDeclarationSyntax tds) => tds switch { ClassDeclarationSyntax => "class", RecordDeclarationSyntax => "record", StructDeclarationSyntax => "struct", _ => "-" }; } }
context.AddSource
字符串形式的源码添加到编译中,SourceText
原文本抽象类,SourceText.From
静态方法,Code指定要创建的源码内容,Encoding设置保存的编码格式,默认为UTF8,context.SyntaxReceiver
可以获取在初始化期间注册的ISyntaxReceiver
,获取创建的实例
实现ISyntaxReceiver
ISyntaxReceiver
接口作为一个语法收集器的定义,可实现该接口,通过对该接口的实现,可过滤生成器所需
public class CustomSyntaxReceiver : ISyntaxReceiver{ public List<BaseTypeDeclarationSyntax> Syntaxes { get; } = new(); /// <summary> /// 访问语法树 /// </summary> /// <param name="syntaxNode"></param> public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { if (syntaxNode is BaseTypeDeclarationSyntax cds) { Syntaxes.Add(cds); } }}
可以再此处进行过滤,如通过ClassDeclarationSyntax
过滤Class
类,当然也可以改为BaseTypeDeclarationSyntax
,或者也可以使用InterfaceDeclarationSyntax
添加接口类等等
调试
对于Source Generator可以通过添加Debugger.Launch()
的形式进行对编译时的生成器进行调试,可以通过它很便捷的一步步调试代码.
public void Initialize(GeneratorInitializationContext context) { Debugger.Launch(); ...... }
Library&Properties
<ItemGroup> <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup>
ReferenceOutputAssembly
:如果设置为false,则不包括引用项目的输出作为此项目的引用,但仍可确保在此项目之前生成其他项目。 默认为 true。OutputItemType
:可选项,将目标要输出的类型,默认为空,如果引用值设置为true(默认值),那么目标输出将为编译器的引用。
Reference
https://github.com/hueifeng/BlogSample/tree/master/src/SourceGeneratorDemo
原文转载:http://www.shaoqun.com/a/632662.html
菜鸟网:https://www.ikjzd.com/w/1547
心怡物流:https://www.ikjzd.com/w/1327
前言SourceGenerators顾名思义代码生成器,可进行创建编译时代码,也就是所谓的编译时元编程,这可让一些运行时映射的代码改为编译时,同样也加快了速度,我们可避免那种昂贵的开销,这是有价值的。实现ISourceGenerator集成ISourceGenerator接口,实现接口用于代码生成策略,它的生命周期由编译器控制,它可以在编译时创建时创建并且添加到编译中的代码,它为我们提供了编译时元
blibli:https://www.ikjzd.com/w/1676
cima:https://www.ikjzd.com/w/1372
prezi:https://www.ikjzd.com/w/1751
亚马逊产品卖不出去,你可能犯了6种致命错误!:https://www.ikjzd.com/home/107956
亚马逊站内CPC广告,怎样才能做好:https://www.ikjzd.com/tl/5377
知道吗?速卖通运费模板的设置关联属性是什么?:https://www.ikjzd.com/home/100276
No comments:
Post a Comment