Source Generator-扩充原有代码

Posted 摧残一生 涅槃重生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Source Generator-扩充原有代码相关的知识,希望对你有一定的参考价值。

我们经常会遇到,原有代码中新增方法,扩展我们自己写的代码。这个使用Source Generator也可以实现

  1. 在上一章的接触上新增类库(AugmentingGeneratorMethod)

  2. 添加Microsoft.CodeAnalysis.Analyzers 和 Microsoft.CodeAnalysis.CSharp引用:

      <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3">
          <PrivateAssets>all</PrivateAssets>
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
      </ItemGroup>
    
  3. 在SourceGeneratorConsole项目中添加一个类AugmentClass,添加如下代码:

    namespace SourceGeneratorConsole
    
        public partial class AugmentClass
        
            public void AugmentMethod()
            
                // 调用代码生成器中的方法
                this.GeneratedMethod();
            
        
    
    

    调用的GeneratedMethod方法为需要代码生成器增加的,其中代码生成器需要获得命名空间和该class类才能让this生效。

  4. 在AugmentingGeneratorMethod中新建一个cs文件,命名为AugmentingGenerator。添加如下代码

    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
    using Microsoft.CodeAnalysis.Text;
    using System;
    using System.Diagnostics;
    using System.Text;
    
    namespace AugmentingGeneratorMethod
    
        [Generator]
        public class AugmentingGenerator : ISourceGenerator
        
            public void Initialize(GeneratorInitializationContext context)
            
                // 自定义一个语法接收器的工厂,然后通过该工厂向已有的class类中添加新方法
                context.RegisterForSyntaxNotifications(() => new AugmentSyntaxReceiver());
            
    
            public void Execute(GeneratorExecutionContext context)
            
                // 获得创建的语法接收器,然后通过context进行操作
                AugmentSyntaxReceiver syntaxReceiver = (AugmentSyntaxReceiver)context.SyntaxReceiver;
    
                // 通过语法接收器获得class类
                ClassDeclarationSyntax augmentClass = syntaxReceiver.ClassToAugment;
                //判断是否有这个类
                if (augmentClass is null)
                
                    //没有找到就不做任何事情
                    return;
                
    
                //找到了就添加一个方法
                SourceText sourceText = SourceText.From($@"
                    namespace syntaxReceiver.SpaceToAugment.Name.GetText()
                    
                        public partial class augmentClass.Identifier
                        
                            private void GeneratedMethod()
                            
                                Console.WriteLine(""Hello, augmentClass!"");
                            
                        
                    ", Encoding.UTF8);
                context.AddSource("augmentClass.Generated.cs", sourceText);
            
        
    
    
  5. 在AugmentingGeneratorMethod项目中添加语法接收器(AugmentSyntaxReceiver),代码如下

    using Microsoft.CodeAnalysis.CSharp.Syntax;
    using Microsoft.CodeAnalysis;
    
    namespace AugmentingGeneratorMethod
    
        class AugmentSyntaxReceiver : ISyntaxReceiver
        
            // 获得类名
            public ClassDeclarationSyntax ClassToAugment  get; private set; 
            // 获得命名空间
            public NamespaceDeclarationSyntax SpaceToAugment  get; private set; 
    
            public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
            
                //Debugger.Launch();
                if (syntaxNode is NamespaceDeclarationSyntax csd) 
                    SpaceToAugment = csd;
                
                // 判断是否有AugmentClass,如果有则赋值
                if (syntaxNode is ClassDeclarationSyntax cds &&
                    cds.Identifier.ValueText == "AugmentClass")
                
                    
                    ClassToAugment = cds;
                
            
        
    
    
  6. 如果想进行调试,可以使用Debugger.Launch()。

  7. 在SourceGeneratorConsole的Program中添加调用

    //在原有的代码中进行扩展
    AugmentClass augment = new AugmentClass();
    augment.AugmentMethod();
    
  8. 别忘记,需要引用AugmentingGeneratorMethod项目,并添加两个属性

      <ItemGroup>
        <ProjectReference Include="..\\SourceGeneratorXmlMethod\\SourceGeneratorXmlMethod.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
      </ItemGroup>
    
  9. 编译运行后,结果正常显示

  10. 总结

    当生成出现错误时,大概率是未添加Generator项目的引用或者未添加OutputItemType和ReferenceOutputAssembly属性

以上是关于Source Generator-扩充原有代码的主要内容,如果未能解决你的问题,请参考以下文章

OC 中 类目延展和协议

Source Generator-添加诊断

C# 强大的新特性 Source Generator

Roslyn Source Generator 未在 .net 框架 4.7.2 中生成任何源

可以物理访问 Source Generator 创建的文件吗?

9.类的延展