C# IIncrementalGenerator干点啥

生成器项目

得基于.Net Stander 2.0
重要:<IsRoslynComponent>true</IsRoslynComponent>、<IncludeBuildOutput>false</IncludeBuildOutput>、    <PackageReference Include="Microsoft.CodeAnalysis" Version="4.14.0" />

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
      <IncludeBuildOutput>false</IncludeBuildOutput>
      <LangVersion>latest</LangVersion>
      <IsRoslynComponent>true</IsRoslynComponent>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis" Version="4.14.0" />
  </ItemGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" PrivateAssets="all" />
    </ItemGroup>
    <ItemGroup>
      <ProjectReference Include="..\..\MasterNeverDown.SA\MasterNeverDown.SA.csproj" />
    </ItemGroup>
</Project>


生成器示例

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace LoggingGenerator
{
    [Generator]
    public class LoggingGenerator : IIncrementalGenerator
    {
        // 记录初始化过程
        public LoggingGenerator()
        {
            System.Diagnostics.Debug.WriteLine("LoggingGenerator initialized");
        }

        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            //Debugger.Launch();
            // 记录初始化开始
            LogMessage("Initializing generator");

            // 筛选出标记了[LogMethod]特性的方法
            IncrementalValuesProvider<IMethodSymbol> methodsToLog = context.SyntaxProvider
                .CreateSyntaxProvider(
                    predicate: (s, _) => IsMethodDeclarationWithAttribute(s),
                    transform: (ctx, _) => GetMethodSymbol(ctx))
                .Where(m => m != null)!;

            // 注册代码生成操作
            context.RegisterSourceOutput(methodsToLog.Collect(),
                (spc, methods) => GenerateLoggingCode(spc, methods));

            // 记录初始化完成
            LogMessage("Generator initialization completed");
        }

        private bool IsMethodDeclarationWithAttribute(SyntaxNode node)
        {
            // 检查是否为方法声明且有LogMethod特性
            if (node is not Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax methodSyntax)
                return false;

            return methodSyntax.AttributeLists.Any(al =>
                al.Attributes.Any(a => a.Name.ToString() == "LogMethod"));
        }

        private IMethodSymbol? GetMethodSymbol(GeneratorSyntaxContext context)
        {
            var methodSyntax = (Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax)context.Node;
            return context.SemanticModel.GetDeclaredSymbol(methodSyntax) as IMethodSymbol;
        }

        private void GenerateLoggingCode(SourceProductionContext context, ImmutableArray<IMethodSymbol> methods)
        {
            // 记录代码生成开始
            LogMessage($"Starting code generation for {methods.Length} methods");

            foreach (var method in methods)
            {
                try
                {
                    // 生成方法日志代码
                    var source = GenerateMethodLogging(method);
                    var hintName = $"{method.ContainingType.Name}_{method.Name}.g.cs";

                    context.AddSource(hintName, SourceText.From(source, Encoding.UTF8));

                    // 记录成功生成
                    LogMessage($"Generated logging code for {method.ContainingType.Name}.{method.Name}");
                }
                catch (Exception ex)
                {
                    // 记录生成失败
                    LogError($"Failed to generate code for {method.ContainingType.Name}.{method.Name}: {ex.Message}");
                }
            }

            // 记录代码生成完成
            LogMessage("Code generation completed");
        }

        private string GenerateMethodLogging(IMethodSymbol method)
        {
            // 构建方法日志代码
            var className = method.ContainingType.Name;
            var methodName = method.Name;
            var parameters = string.Join(", ", method.Parameters.Select(p => $"{p.Type} {p.Name}"));

            var builder = new StringBuilder();
            builder.AppendLine("// <auto-generated>");
            builder.AppendLine("// This code was generated by a source generator.");
            builder.AppendLine("// </auto-generated>");
            builder.AppendLine();
            builder.AppendLine($"namespace {method.ContainingNamespace.ToDisplayString()}");
            builder.AppendLine("{");
            builder.AppendLine($"    public partial class {className}");
            builder.AppendLine("    {");
            builder.AppendLine($"        partial void On{methodName}Executing({parameters});");
            builder.AppendLine($"        partial void On{methodName}Executing({parameters})");
            builder.AppendLine("        {");
            builder.AppendLine($"            System.Diagnostics.Debug.WriteLine(\"Entering method {methodName}\");");

            // 记录参数
            foreach (var param in method.Parameters)
            {
                builder.AppendLine($"            System.Diagnostics.Debug.WriteLine(\"  Parameter {param.Name}: \" + ({param.Name}?.ToString() ?? \"null\"));");
            }

            builder.AppendLine("        }");
            builder.AppendLine();
            builder.AppendLine($"        partial void On{methodName}Executed({parameters});");
            builder.AppendLine($"        partial void On{methodName}Executed({parameters})");
            builder.AppendLine("        {");
            builder.AppendLine($"            System.Diagnostics.Debug.WriteLine(\"Exiting method {methodName}\");");
            builder.AppendLine("        }");
            builder.AppendLine("    }");
            builder.AppendLine("}");

            return builder.ToString();
        }

        // 日志方法 - 可根据需要调整输出方式
        private void LogMessage(string message)
        {
            System.Diagnostics.Debug.WriteLine($"[LoggingGenerator] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
        }

        private void LogError(string message)
        {
            System.Diagnostics.Debug.WriteLine($"[LoggingGenerator ERROR] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
        }
    }
}

项目代码

重要: OutputItemType="Analyzer" ReferenceOutputAssembly="false"

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis" Version="4.14.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MasterNeverDown.SA\MasterNeverDown.SA.csproj" />
    <ProjectReference Include="..\Sd\Sd\Sd.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  </ItemGroup>
	<ItemGroup>
		<Compilervisibility Include="PublicApiAnalyzer" Version="1.0.0" />
	</ItemGroup>
</Project>

结果

在依赖项=》分析器=》项目生成g.cs,注意变更源生成器需要重新打开工程来刷新新生成的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值