using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace JiShe.CollectBus.IncrementalGenerator { /// /// 复杂类型增量源生成器 /// [Generator(LanguageNames.CSharp)] public class ComplexTypeSourceAnalyzers : IIncrementalGenerator { private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute"; public void Initialize(IncrementalGeneratorInitializationContext context) { //Debugger.Launch(); // 步骤1:筛选带有 [SourceAnalyzers] 的类 var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (s, _) => IsClassWithAttribute(s), transform: static (ctx, _) => GetClassDeclaration(ctx)) .Where(static c => c is not null); // 步骤2:合并编译信息 var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); context.RegisterSourceOutput(compilationAndClasses, (spc, source) => GenerateCode(source.Left, source.Right!, spc)); } private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0; private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context) { var classDecl = (ClassDeclarationSyntax)context.Node; var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName); foreach (var attribute in classDecl.AttributeLists.SelectMany(al => al.Attributes)) { var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; if (symbol is IMethodSymbol ctor && SymbolEqualityComparer.Default.Equals(ctor.ContainingType, attributeType)) { return classDecl; } } return null; } /// /// 递归获取所有层级的属性 /// /// /// private static IEnumerable GetAllPropertiesInHierarchy(INamedTypeSymbol classSymbol) { var currentSymbol = classSymbol; while (currentSymbol != null) { foreach (var prop in currentSymbol.GetMembers().OfType()) { yield return prop; } currentSymbol = currentSymbol.BaseType; // 向上遍历基类 } } /// /// 生成代码 /// /// /// /// private static void GenerateCode( Compilation compilation, IEnumerable classes, SourceProductionContext context) { var processedTypes = new HashSet(SymbolEqualityComparer.Default); if (!classes.Any()) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor("GEN002", "没有目标类", "没有找到SourceAnalyzers标记的类", "Debug", DiagnosticSeverity.Warning, true), Location.None)); } foreach (var classDecl in classes.Distinct()) { var model = compilation.GetSemanticModel(classDecl.SyntaxTree); var classSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol; if (classSymbol == null || !processedTypes.Add(classSymbol)) { context.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor("GEN003", "无效符号", $"类名称为{classDecl.Identifier.Text} 符号为空", "Error", DiagnosticSeverity.Error, true), Location.None)); continue; } var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes); context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3); } // 生成工厂注册代码 context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode()); } /// /// 获取泛型参数 /// /// /// public static string GetGenericParams(INamedTypeSymbol symbol) { if (!symbol.IsGenericType) return ""; var parameters = symbol.TypeParameters.Select(t => t.Name); return $"<{string.Join(", ", parameters)}>"; } /// /// 生成标准属性的访问器 /// /// /// /// private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) { var parentType = prop.ContainingType.ToDisplayString(); code.AppendLine($" public static {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};"); if (prop.SetMethod != null) { code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;"); } } /// /// 构建实体访问器代码(支持泛型) /// private static string BuildAccessorsForSourceEntity( INamedTypeSymbol classSymbol, Compilation compilation, HashSet processedTypes) { var code = new StringBuilder(); code.AppendLine("// "); code.AppendLine("#nullable enable"); code.AppendLine("using System;"); code.AppendLine("using System.Collections.Generic;"); code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;"); code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); code.AppendLine(); // 处理泛型类型参数 var genericParams = classSymbol.IsGenericType ? $"<{string.Join(", ", classSymbol.TypeParameters.Select(t => t.Name))}>" : ""; code.AppendLine( $"public sealed class {classSymbol.Name}Accessor{genericParams} " + $": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>"); code.AppendLine("{"); var propList = GetAllPropertiesInHierarchy(classSymbol); foreach (var prop in propList) { // 安全类型转换 if (prop.Type is not ITypeSymbol propType) continue; if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) { GenerateTupleAccessors(prop, tupleType, code, classSymbol); } else if (propType is INamedTypeSymbol namedType) { GenerateStandardAccessors(prop, namedType, code); } } //生成当前类属性名称集合 GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol); //生成当前类属性访问 GetGeneratePropertyValueForSourceEntity( propList, code, compilation, classSymbol); //生成当前类属性设置 SetGeneratePropertyValueForSourceEntity( propList, code, compilation, classSymbol); code.AppendLine("}"); return code.ToString(); } /// /// 生成泛型ValueTuple 元组访问器 /// private static void GenerateTupleAccessors( IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code, INamedTypeSymbol classSymbol) { var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var tupleElements = tupleType.TupleElements; for (int i = 0; i < tupleElements.Length; i++) { var element = tupleElements[i]; var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var elementName = element.Name; // Getter保持不变 code.AppendLine( $" public static {elementType} Get{prop.Name}_{elementName}" + $"({parentType} obj) => obj.{prop.Name}.{elementName};"); // Setter修复:使用元组字面量 if (prop.SetMethod != null) { var valueExpressions = tupleElements.Select((e, idx) => idx == i ? "value" : $"obj.{prop.Name}.{e.Name}" ).ToList(); // 关键修复:生成正确的元组字面量表达式 code.AppendLine( $" public static void Set{prop.Name}_{elementName}" + $"({parentType} obj, {elementType} value) => " + $"obj.{prop.Name} = ({string.Join(", ", valueExpressions)});"); } } } /// /// 处理System.Tuple类型的访问器生成 /// private static void GenerateSystemTupleAccessors( IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code, INamedTypeSymbol classSymbol) { var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var elementTypes = tupleType.TypeArguments; var tupleTypeName = tupleType.ToDisplayString(); for (int i = 0; i < elementTypes.Length; i++) { var elementType = elementTypes[i].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var elementName = $"Item{i + 1}"; // Getter code.AppendLine( $" public static {elementType} Get{prop.Name}_{elementName}" + $"({parentType} obj) => obj.{prop.Name}.{elementName};"); // Setter if (prop.SetMethod != null) { var assignments = elementTypes.Select((_, idx) => idx == i ? "value" : $"obj.{prop.Name}.Item{idx + 1}" ).ToList(); code.AppendLine( $" public static void Set{prop.Name}_{elementName}" + $"({parentType} obj, {elementType} value) => " + $"obj.{prop.Name} = new {tupleTypeName}({string.Join(", ", assignments)});"); } } } /// /// 增强的工厂类实现 /// private static string BuildFactoryCode() { return """ using System; using System.Collections.Concurrent; using System.Reflection; namespace JiShe.CollectBus.Analyzers.Shared; public static class SourceEntityAccessorFactory { private static readonly ConcurrentDictionary _accessors = new(); public static ISourceEntityAccessor GetAccessor() { return (ISourceEntityAccessor)_accessors.GetOrAdd(typeof(T), t => { var typeName = $"{t.Namespace}.{t.Name}Accessor"; if (t.IsGenericType) { var genericArgs = t.GetGenericArguments(); var genericDef = t.GetGenericTypeDefinition(); typeName = $"{genericDef.Namespace}.{genericDef.Name}Accessor`{genericArgs.Length}"; } var type = Type.GetType(typeName) ?? Assembly.GetAssembly(t)?.GetType(typeName) ?? throw new InvalidOperationException($"Accessor type {typeName} not found"); return t.IsGenericType ? Activator.CreateInstance(type.MakeGenericType(t.GetGenericArguments())) : Activator.CreateInstance(type); }); } } """; } /// /// 属性访问生成逻辑 /// /// 属性集合 /// /// /// private static void GetGeneratePropertyValueForSourceEntity( IEnumerable propList, StringBuilder code, Compilation compilation, INamedTypeSymbol classSymbol) { code.AppendLine($" public object GetPropertyValue({classSymbol} targetEntity, string propertyName)"); code.AppendLine(" {"); code.AppendLine(" return propertyName switch"); code.AppendLine(" {"); foreach (var prop in propList) { if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { code.AppendLine( $" \"{prop.Name}.{element.Name}\" => " + $"Get{prop.Name}_{element.Name}(targetEntity),"); } } else { code.AppendLine( $" \"{prop.Name}\" => " + $"Get{prop.Name}(targetEntity),"); } } code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")"); code.AppendLine(" };"); code.AppendLine(" }"); } /// /// 属性设置生成逻辑 /// /// 属性集合 /// /// /// private static void SetGeneratePropertyValueForSourceEntity( IEnumerable propList, StringBuilder code, Compilation compilation, INamedTypeSymbol classSymbol) { code.AppendLine($" public void SetPropertyValue({classSymbol} targetEntity, string propertyName, object value)"); code.AppendLine(" {"); code.AppendLine(" switch (propertyName)"); code.AppendLine(" {"); foreach (var prop in propList) { if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); code.AppendLine($" case \"{prop.Name}.{element.Name}\":"); code.AppendLine($" Set{prop.Name}_{element.Name}("); code.AppendLine($" targetEntity, ({elementType})value);"); code.AppendLine(" break;"); } } else if (prop.SetMethod != null) { var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); code.AppendLine($" case \"{prop.Name}\":"); code.AppendLine($" Set{prop.Name}("); code.AppendLine($" targetEntity, ({propType})value);"); code.AppendLine(" break;"); } } code.AppendLine(" default:"); code.AppendLine(" throw new ArgumentException($\"Unknown property: {propertyName}\");"); code.AppendLine(" }"); code.AppendLine(" }"); } /// /// 属性名称集合 /// /// 属性集合 /// /// /// private static void GeneratePropertyListForSourceEntity( IEnumerable propList, StringBuilder code, Compilation compilation, INamedTypeSymbol classSymbol) { code.AppendLine(" public List PropertyList {get;} = new List()"); code.AppendLine(" {"); List tempPropList = new List(); foreach (var prop in propList) { if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { tempPropList.Add($"\"{prop.Name}.{element.Name}\""); } } else { tempPropList.Add($"\"{prop.Name}\""); } } code.Append(string.Join(",", tempPropList)); code.AppendLine(" };"); } } }