using JiShe.CollectBus.Analyzers.Shared; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; using System.Collections.Immutable; 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 semanticModel = context.SemanticModel; // 获取类符号 var classSymbol = semanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol; if (classSymbol == null) return null; // 检查是否包含 SourceAnalyzers 特性 var sourceAnalyzerAttr = classSymbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == AttributeFullName); // 必须包含 EntityType 参数 if (sourceAnalyzerAttr == null || sourceAnalyzerAttr.ConstructorArguments.Length == 0) { return null; } return classDecl; //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) { // 获取 SourceAnalyzers 特性的 EntityType 参数 var sourceAnalyzerAttr = classSymbol.GetAttributes() .FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == AttributeFullName); // 解析 EntityType 枚举值 string entityTypeValue = "EntityTypeEnum.Other"; // 默认值 if (sourceAnalyzerAttr != null && sourceAnalyzerAttr.ConstructorArguments.Length > 0) { var arg = sourceAnalyzerAttr.ConstructorArguments[0]; if (arg.Kind == TypedConstantKind.Enum && arg.Type is INamedTypeSymbol enumType) { int enumValue = (int)arg.Value!; entityTypeValue = GetEnumMemberName(enumType, enumValue); } } var code = new StringBuilder(); code.AppendLine("// "); code.AppendLine("#nullable enable"); code.AppendLine("using System;"); code.AppendLine("using System.Reflection;"); code.AppendLine("using System.Collections.Generic;"); code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;"); code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); code.AppendLine(); // 处理泛型类型名称 var accessibility = classSymbol.DeclaredAccessibility switch { Accessibility.Public => "public", _ => "internal" }; var genericParams = classSymbol.IsGenericType ? $"<{string.Join(", ", classSymbol.TypeParameters.Select(t => t.Name))}>" : ""; code.AppendLine( $"{accessibility} sealed class {classSymbol.Name}Accessor{genericParams} " + // 保留泛型参数 $": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>"); code.AppendLine("{"); var propList = GetAllPropertiesInHierarchy(classSymbol); //类名称 code.AppendLine($" public string EntityName {{get;}} = \"{classSymbol.Name}\";"); // 添加 EntityType 属性 code.AppendLine($" public EntityTypeEnum? EntityType {{ get; }} = {entityTypeValue};"); foreach (var prop in propList) { // 安全类型转换 if (prop.Type is not ITypeSymbol propType) continue; if (propType is INamedTypeSymbol namedType) { GenerateStandardAccessors(prop, namedType, code); } if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) { GenerateTupleAccessors(prop, tupleType, code); } } //生成当前类属性名称集合 GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol); //生成当前类属性信息集合 GenerateEntityMemberInfoList(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) { var parentType = prop.ContainingType.ToDisplayString(); var tupleElements = tupleType.TupleElements; for (int i = 0; i < tupleElements.Length; i++) { var element = tupleElements[i]; var elementType = element.Type.ToDisplayString(); 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) { code.AppendLine($"public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value) => obj.{prop.Name} = ({string.Join(", ", GetTupleElements(prop.Name, tupleElements, i))});"); } } } private static IEnumerable GetTupleElements( string propName, ImmutableArray elements, int targetIndex) { for (int i = 0; i < elements.Length; i++) { yield return i == targetIndex ? "value" : $"obj.{propName}.{elements[i].Name}"; } } /// /// 处理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 isGeneric = t.IsGenericType; var genericTypeDef = isGeneric ? t.GetGenericTypeDefinition() : null; var arity = isGeneric ? genericTypeDef!.GetGenericArguments().Length : 0; // 构建访问器类名 var typeName = isGeneric ? $"{t.Namespace}.{genericTypeDef!.Name.Split('`')[0]}Accessor`{arity}" : $"{t.Namespace}.{t.Name}Accessor"; // 尝试从当前程序集加载 var accessorType = Assembly.GetAssembly(t)!.GetType(typeName) ?? throw new InvalidOperationException($"Accessor type {typeName} not found"); // 处理泛型参数 if (isGeneric && accessorType.IsGenericTypeDefinition) { accessorType = accessorType.MakeGenericType(t.GetGenericArguments()); } return Activator.CreateInstance(accessorType)!; }); } } """; } /// /// 属性访问生成逻辑 /// /// 属性集合 /// /// /// 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) { code.AppendLine( $" \"{prop.Name}\" => " + $"Get{prop.Name}(targetEntity),"); 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),"); } } } 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) { 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;"); 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;"); } } } 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 PropertyNameList {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(" };"); } /// /// 生成当前类属性信息集合 /// private static void GenerateEntityMemberInfoList( IEnumerable propList, StringBuilder code, Compilation compilation, INamedTypeSymbol classSymbol) { code.AppendLine(" public List MemberList { get; } = new()"); code.AppendLine(" {"); var initializerLines = new List(); foreach (var prop in propList) { var entityType = prop.ContainingType.ToDisplayString();//entity 实体类型名称 var propType = prop.Type;//实体属性的类型 var propTypeName = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); // var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32") // 处理可空类型,获取底层具体类型名称 var declaredTypeName = propType switch { INamedTypeSymbol { OriginalDefinition.SpecialType: SpecialType.System_Nullable_T } nullableType => nullableType.TypeArguments[0].Name, // 提取如 "Int32" _ => propType.Name }; // 处理主属性 var propAttributes = prop.GetAttributes() .Where(a => !IsCompilerGeneratedAttribute(a)) .ToList(); var attributeInitializers = propAttributes .Select(GenerateAttributeInitializer) .Where(s => !string.IsNullOrEmpty(s)); var mainMember = new StringBuilder(); mainMember.Append( $"new EntityMemberInfo(" + $"\"{prop.Name}\", " + $"typeof({propTypeName}), " + $"\"{declaredTypeName}\", " + $"(e) => Get{prop.Name}(({entityType})e), " + $"(e, v) => Set{prop.Name}(({entityType})e, ({propTypeName})v))"); if (attributeInitializers.Any()) { mainMember.AppendLine(); mainMember.Append(" { CustomAttributes = new List"); mainMember.Append($" {{ {string.Join(", ", attributeInitializers)} }} }}"); } initializerLines.Add(mainMember.ToString()); // 处理元组元素,(暂不需要处理元组元素的特性) if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);//元组元素的类型 var elementName = element.Name;//元组元素名称 var elementDeclaredName = element.Type.Name;//元组元素类型名称 initializerLines.Add( $"new EntityMemberInfo(" + $"\"{prop.Name}.{elementName}\", " + $"typeof({elementType}), " + $"typeof({elementType}).Name, " +//$"\"{elementDeclaredName}\", " + $"(e) => Get{prop.Name}_{elementName}(({entityType})e), " + $"(e, v) => Set{prop.Name}_{elementName}(({entityType})e, ({elementType})v))"); } } } code.AppendLine(string.Join(",\n", initializerLines)); code.AppendLine(" };"); } private static string GenerateAttributeInitializer(AttributeData attribute) { if (attribute.AttributeClass == null) return string.Empty; var attributeClass = attribute.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var args = attribute.ConstructorArguments; var namedArgs = attribute.NamedArguments; var parameters = new List(); foreach (var arg in args) { parameters.Add(ConvertTypedConstantToCode(arg)); } var constructorArgs = string.Join(", ", parameters); var initializer = new StringBuilder(); initializer.Append($"new {attributeClass}({constructorArgs})"); if (namedArgs.Any()) { initializer.Append(" { "); var namedArgsList = namedArgs.Select(n => $"{n.Key} = {ConvertTypedConstantToCode(n.Value)}"); initializer.Append(string.Join(", ", namedArgsList)); initializer.Append(" }"); } return initializer.ToString(); } private static string ConvertTypedConstantToCode(TypedConstant constant) { if (constant.IsNull) return "null"; switch (constant.Kind) { case TypedConstantKind.Array: var elements = constant.Values.Select(ConvertTypedConstantToCode); return $"new[] {{ {string.Join(", ", elements)} }}"; case TypedConstantKind.Type: var typeSymbol = (ITypeSymbol)constant.Value!; return $"typeof({typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)})"; case TypedConstantKind.Enum: return ConvertEnumTypedConstant(constant); default: return ConvertPrimitiveConstant(constant); } } private static string ConvertEnumTypedConstant(TypedConstant constant) { var enumType = constant.Type!; var enumValue = constant.Value!; var enumTypeName = enumType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); foreach (var member in enumType.GetMembers().OfType()) { if (member.ConstantValue != null && member.ConstantValue.Equals(enumValue)) return $"{enumTypeName}.{member.Name}"; } return $"({enumTypeName})({enumValue})"; } private static string ConvertPrimitiveConstant(TypedConstant constant) { var value = constant.Value!; return value switch { string s => $"\"{s}\"", char c => $"'{c}'", bool b => b ? "true" : "false", _ => value.ToString() }; } private static bool IsCompilerGeneratedAttribute(AttributeData attribute) { return attribute.AttributeClass?.ToDisplayString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; } /// /// 获取枚举的参数 /// /// /// /// private static string GetEnumMemberName(INamedTypeSymbol enumType, int value) { foreach (var member in enumType.GetMembers().OfType()) { if (member.ConstantValue is int intValue && intValue == value) { return $"{enumType.ToDisplayString()}.{member.Name}"; } } return $"{enumType.ToDisplayString()}.Other"; } } }