当前位置: 首页 > news >正文

C# .NET Core Source Generator(C# .NET Core 源生成器)

    源生成器是一款功能强大的工具,允许开发人员在编译过程中自动生成代码。它有助于减少样板代码、提高性能并启用新的编码模式。在本文中,我们将演示如何创建自定义源生成器,以便根据给定方法集的特定条件生成代码。

什么是源生成器?

    源生成器是在编译期间运行的一段代码,它可以检查您的程序以生成与其余代码一起编译的附加文件。

源生成器如何工作?

    在编译过程中,源生成器会分析代码和元数据,并基于这些分析生成额外的源代码。这些代码就像编译器的插件,在编译过程中执行。当编译器加载源生成器时,它会分析代码和元数据,以识别与源生成器相关的语法节点和语义信息。

    源生成器会分析语法节点,并根据分析结果生成附加源代码。生成的代码会添加到编译中,就像开发人员编写的一样。编译完成后,生成的代码会包含在程序集中。

何时使用源生成器?

    源生成器非常适合需要自动执行重复性任务、强制执行编码模式或根据代码库中的特定条件生成代码的情况。以下是源生成器特别有用的一些情况:

    1、减少样板代码:如果您发现自己一遍又一遍地编写相同的代码,源代码生成器可以自动为您生成该代码。这可以节省时间并降低手动代码重复导致错误的可能性。

    2、提升性能:源生成器可以生成针对特定场景(例如数据序列化或网络通信)优化的代码。这可以通过减少执行这些操作所需的开销来帮助提高应用程序的性能。

    3、启用新的编码模式:源生成器可用于启用新的编码模式,例如编译时依赖注入或面向方面编程。这可以帮助开发人员编写更模块化、更易于维护且更易于测试和调试的代码。

    4、适应不断变化的需求:源生成器可用于使代码适应不断变化的需求,例如外部 API 的变更或业务逻辑的变更。这有助于减少所需的手动代码更新量,并提高代码库的整体灵活性。

    5、生成横切关注点的代码:源生成器可用于生成横切关注点的代码,例如日志记录、错误处理或性能监控。这有助于确保这些问题在整个应用程序中得到一致处理,并降低手动编码导致错误的风险。

了解源生成器的组件

    源生成器由两个主要组件组成,它们协同工作以提供无缝且高效的代码生成过程:

    ISyntaxReceiver和ISourceGenerator。通过了解这些组件及其关系,您可以根据特定需求创建自定义的源生成器。

    ISyntaxReceiver负责在编译过程中收集语法节点,并根据特定条件进行过滤。ISourceGenerator负责根据ISyntaxReceiver收集到的过滤后的语法节点生成代码。

这两个组件协同工作如下:

    1、ISyntaxReceiver在编译过程中收集并过滤语法节点。

    2、ISourceGenerator从ISyntaxReceiver接收过滤后的语法节点。

    3、ISourceGenerator根据过滤后的语法节点生成代码。

    您也可以直接在 ISourceGenerator 的 Execute 方法中过滤语法节点,但使用 ISyntaxReceiver 更高效,因为它允许您在编译过程中过滤语法节点,从而避免不必要的开销。

逐步创建自定义源生成器

1、设置源生成器项目

    创建一个新的类库(.NET Standard)项目,目标是netstandard2.0。要使用源生成器,您需要将以下 NuGet 包添加到您的项目中:
    - Microsoft.CodeAnalysis.CSharp
    - Microsoft.CodeAnalysis.Analyzers

2、实现自定义语法接收器 

public class CustomSyntaxReceiver : ISyntaxReceiver
 {
     public List<MethodDeclarationSyntax> CandidateMethods { get; } = new();
     public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
     {
         if (syntaxNode is MethodDeclarationSyntax methodDeclaration &&
             methodDeclaration.AttributeLists.Any(al => al.Attributes.Any(a => a.Name.ToString() == "MyCustomAttribute")))
         {
             CandidateMethods.Add(methodDeclaration);
         }
     }
}

3.实现自定义源生成器

[Generator]
public class CustomSourceGenerator : ISourceGenerator
{
   public void Initialize(GeneratorInitializationContext context)
   {
       context.RegisterForSyntaxNotifications(() => new CustomSyntaxReceiver());
   }
   //Inside the `Execute` method, retrieve the SyntaxReceiver and generate code based on the filtered methods. Here's a simple example that generates a static class with a method that prints the names of the filtered methods:
   public void Execute(GeneratorExecutionContext context)
   {
       if (context.SyntaxReceiver is not CustomSyntaxReceiver receiver)
           return;
  
       var sourceBuilder = new StringBuilder();
       sourceBuilder.AppendLine("using System;");
       sourceBuilder.AppendLine("namespace GeneratedCode");
       sourceBuilder.AppendLine("{");
       sourceBuilder.AppendLine("    public static class GeneratedMethodsInfo");
       sourceBuilder.AppendLine("    {");
       sourceBuilder.AppendLine("        public static void PrintMethodNames()");
       sourceBuilder.AppendLine("        {");
  
       foreach (var method in receiver.CandidateMethods)
       {
           sourceBuilder.AppendLine($"            Console.WriteLine(\"{method.Identifier}\");");
       }
  
       sourceBuilder.AppendLine("        }");
       sourceBuilder.AppendLine("    }");
       sourceBuilder.AppendLine("}");
  
       context.AddSource("GeneratedMethodsInfo", sourceBuilder.ToString());
    }
}

4.从项目中添加源生成器作为分析器

<!-- replacing paths and names appropriately -->
<ItemGroup>

    <ProjectReference Include="path-to-sourcegenerator-project.csproj" 
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="false" />
</ItemGroup>

    通过实现自定义的 ISyntaxReceiver 和 ISourceGenerator,您可以创建一个强大而高效的 Source Generator,根据特定条件生成代码。使用 ISyntaxReceiver 允许您在编译过程中过滤语法节点,从而减少开销并提高性能。

    总而言之,了解源生成器的各个组件及其关系对于创建符合您特定需求的自定义源生成器至关重要。通过利用 ISyntaxReceivers 和 ISourceGenerators 的强大功能,您可以增强开发流程,并充分利用 C# 中源生成器提供的优势。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。 

http://www.xdnf.cn/news/1006309.html

相关文章:

  • md文件转word文档
  • 单元测试基本步骤
  • Spring MVC 常用请求处理注解总结
  • llm agent
  • OpenCV CUDA模块图像变形------对图像进行任意形式的重映射(Remapping)操作函数remap()
  • Spring Boot3批式访问Dify聊天助手接口
  • Vue 中 this.$emit(‘mount‘) 的妙用
  • 如何在 Discourse AI 中设置 Gemini API
  • 多串口卡使用
  • 软件测试BUG
  • 【小工具】-Doxygen01
  • slam--非线性优化
  • BEV和OCC学习-8:mmdet3d 3D分割demo测试
  • 如何利用单细胞转录组进行细胞图谱和疾病机制研究?
  • 爬虫实践:TOP250电影数据
  • 从数学到代码:一文详解埃拉托色尼筛法(埃式筛)
  • 阳台光伏防逆流电表革新者:安科瑞ADL200N-CT/D16-WF
  • ref 应用于对象类型的一个案例
  • CKA考试知识点分享(11)---CRD
  • JavaScript DOM 操作与事件处理全解析
  • BeanUtil.copyProperties()进行属性拷贝时如何忽略NULL值——CopyOptions配置详解
  • 高效管理Python环境:Miniforge、pyenv和Poetry深度对比与应用
  • 建筑业应用:机器人如何改变未来建筑业发展方向
  • 介绍一下 TCP方式程序的通讯,服务器机与客户机
  • 使用 DeepSeek 为 TDengine 创建专属知识库
  • 部署安装maven和mvnd
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | RandomChoicePicker(标签生成)
  • 西门子PLC读取梅安森风压传感器数据
  • 【2025】深度学习环境搭建记录
  • inet_addr()和inet_aton()函数详解