diff --git a/JiShe.CollectBus.sln b/JiShe.CollectBus.sln index 2e5826f..0232b6d 100644 --- a/JiShe.CollectBus.sln +++ b/JiShe.CollectBus.sln @@ -62,7 +62,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Docs", "0.Docs", "{D8346C readme.md = readme.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.SourceExtend", "shared\JiShe.CollectBus.SourceExtend\JiShe.CollectBus.SourceExtend.csproj", "{A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.IncrementalGenerator", "shared\JiShe.CollectBus.IncrementalGenerator\JiShe.CollectBus.IncrementalGenerator.csproj", "{828D20BC-454E-0467-B29D-429B25F1E0CA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -150,10 +150,10 @@ Global {75B7D419-C261-577D-58D6-AA3ACED9129F}.Debug|Any CPU.Build.0 = Debug|Any CPU {75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.ActiveCfg = Release|Any CPU {75B7D419-C261-577D-58D6-AA3ACED9129F}.Release|Any CPU.Build.0 = Release|Any CPU - {A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9}.Release|Any CPU.Build.0 = Release|Any CPU + {828D20BC-454E-0467-B29D-429B25F1E0CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {828D20BC-454E-0467-B29D-429B25F1E0CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {828D20BC-454E-0467-B29D-429B25F1E0CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {828D20BC-454E-0467-B29D-429B25F1E0CA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -179,7 +179,7 @@ Global {8A61DF78-069B-40B5-8811-614E2960443E} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} {E27377CC-E2D3-4237-060F-96EA214D3129} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} {75B7D419-C261-577D-58D6-AA3ACED9129F} = {3C3F9DB2-EC97-4464-B49F-BF1A0C2B46DC} - {A34A4EA6-AEB0-4199-8E3A-6F042DBB51D9} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B} + {828D20BC-454E-0467-B29D-429B25F1E0CA} = {EBF7C01F-9B4F-48E6-8418-2CBFDA51EB0B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} diff --git a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj index afd5a8a..0e8250e 100644 --- a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj +++ b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj @@ -3,7 +3,7 @@ net8.0 enable - enable + enable @@ -11,6 +11,5 @@ - diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index d48f766..3350172 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using JiShe.CollectBus.Common.Attributes; +using JiShe.CollectBus.Common; using JiShe.CollectBus.IoTDB.Attribute; using JiShe.CollectBus.IoTDB.Enums; -using JiShe.CollectBus.IoTDB.Provider; namespace JiShe.CollectBus.IoTDB.Model { diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs index 9b3609c..2a3273b 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using JiShe.CollectBus.Common; using JiShe.CollectBus.IoTDB.Attribute; -using JiShe.CollectBus.IoTDB.Enums; -using JiShe.CollectBus.IoTDB.Provider; +using JiShe.CollectBus.IoTDB.Enums; namespace JiShe.CollectBus.IoTDB.Model { @@ -13,6 +8,7 @@ namespace JiShe.CollectBus.IoTDB.Model /// Tree模型单项数据实体 /// [EntityType(EntityTypeEnum.TreeModel)] + [GenerateAccessors] public class TreeModelSingleMeasuringEntity : IoTEntity { /// diff --git a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj index aefe5e4..b43d994 100644 --- a/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj +++ b/services/JiShe.CollectBus.Application/JiShe.CollectBus.Application.csproj @@ -30,6 +30,8 @@ + + diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index 31a3494..6392b83 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -66,6 +66,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS IssuedMessageHexString = "messageHexString", Timestamps = testTime// DateTimeOffset.UtcNow.ToUnixTimeNanoseconds()//testTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), }; + await _iotDBProvider.InsertAsync(meter); } diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs index 7fe7ebc..a9ddc93 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs @@ -1,10 +1,12 @@ -using JiShe.CollectBus.IoTDB.Attribute; +using JiShe.CollectBus.Common; +using JiShe.CollectBus.IoTDB.Attribute; using JiShe.CollectBus.IoTDB.Enums; -using JiShe.CollectBus.IoTDB.Model; +using JiShe.CollectBus.IoTDB.Model; namespace JiShe.CollectBus.Ammeters { [EntityType(EntityTypeEnum.TreeModel)] + [GenerateAccessors] public class ElectricityMeterTreeModel : IoTEntity { [ATTRIBUTEColumn] diff --git a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs index 1b5c954..552084f 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs @@ -1,16 +1,8 @@ -using JiShe.CollectBus.Common.Encrypt; -using JiShe.CollectBus.Common.Enums; -using JiShe.CollectBus.Common.Models; +using JiShe.CollectBus.Common; using JiShe.CollectBus.IoTDB.Attribute; using JiShe.CollectBus.IoTDB.Enums; using JiShe.CollectBus.IoTDB.Model; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Volo.Abp.Domain.Entities; -using Volo.Abp.Domain.Entities.Auditing; namespace JiShe.CollectBus.IotSystems.MeterReadingRecords { @@ -18,6 +10,7 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// 抄读任务数据 /// [EntityType(EntityTypeEnum.TableModel)] + [GenerateAccessors] public class MeterReadingTelemetryPacketInfo : IoTEntity { /// diff --git a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj index 1914993..44b8a3e 100644 --- a/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj +++ b/services/JiShe.CollectBus.Domain/JiShe.CollectBus.Domain.csproj @@ -25,7 +25,7 @@ - + diff --git a/shared/JiShe.CollectBus.SourceExtend/GenerateAccessorsAttribute.cs b/shared/JiShe.CollectBus.Common/Attributes/GenerateAccessorsAttribute.cs similarity index 59% rename from shared/JiShe.CollectBus.SourceExtend/GenerateAccessorsAttribute.cs rename to shared/JiShe.CollectBus.Common/Attributes/GenerateAccessorsAttribute.cs index b739a54..4912185 100644 --- a/shared/JiShe.CollectBus.SourceExtend/GenerateAccessorsAttribute.cs +++ b/shared/JiShe.CollectBus.Common/Attributes/GenerateAccessorsAttribute.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace JiShe.CollectBus.SourceExtend +namespace JiShe.CollectBus.Common { /// /// 标记需要生成源码的类 diff --git a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj index fdb6bfd..6cf0246 100644 --- a/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj +++ b/shared/JiShe.CollectBus.Common/JiShe.CollectBus.Common.csproj @@ -25,8 +25,7 @@ - - + diff --git a/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs b/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs index 2eb92c5..525b5a2 100644 --- a/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs +++ b/shared/JiShe.CollectBus.Common/Models/ServerApplicationOptions.cs @@ -8,12 +8,12 @@ /// /// 服务器标识 /// - public required string ServerTagName { get; set; } + public string ServerTagName { get; set; } /// /// 系统类型 /// - public required string SystemType { get; set; } + public string SystemType { get; set; } /// /// 首次采集时间 @@ -23,31 +23,31 @@ /// /// 自动验证时间 /// - public required string AutomaticVerificationTime { get; set; } + public string AutomaticVerificationTime { get; set; } /// /// 自动获取终端版时间 /// - public required string AutomaticTerminalVersionTime { get; set; } + public string AutomaticTerminalVersionTime { get; set; } /// /// 自动获取远程通信模块(SIM)版本时间 /// - public required string AutomaticTelematicsModuleTime { get; set; } + public string AutomaticTelematicsModuleTime { get; set; } /// /// 日冻结抄读时间 /// - public required string AutomaticDayFreezeTime { get; set; } + public string AutomaticDayFreezeTime { get; set; } /// /// 月冻结抄读时间 /// - public required string AutomaticMonthFreezeTime { get; set; } + public string AutomaticMonthFreezeTime { get; set; } /// /// 默认协议插件 /// - public required string DefaultProtocolPlugin { get; set; } + public string DefaultProtocolPlugin { get; set; } } } diff --git a/shared/JiShe.CollectBus.IncrementalGenerator/ComplexTypeSourceGenerator.cs b/shared/JiShe.CollectBus.IncrementalGenerator/ComplexTypeSourceGenerator.cs new file mode 100644 index 0000000..1530a2c --- /dev/null +++ b/shared/JiShe.CollectBus.IncrementalGenerator/ComplexTypeSourceGenerator.cs @@ -0,0 +1,223 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.IncrementalGenerator +{ + /// + /// 复杂类型源生成器 + /// + [Generator(LanguageNames.CSharp)] + public class ComplexTypeSourceGenerator : IIncrementalGenerator + { + private const string AttributeFullName = "JiShe.CollectBus.Common.GenerateAccessorsAttribute"; + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + + Debugger.Launch(); + + context.RegisterPostInitializationOutput(ctx => + { + ctx.AddSource("DebugInit.g.cs", "// Generator initialized"); + }); + + // 步骤1:筛选带有 [GenerateAccessors] 的类 + 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; + // foreach (var attributeList in classDecl.AttributeLists) + // { + // foreach (var attribute in attributeList.Attributes) + // { + // var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; + // if (symbol is IMethodSymbol ctor) + // { + // string sdd = ctor.ContainingType.Name; + // var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName); + // if (ctor.ContainingType?.OriginalDefinition?.Equals(attributeType, SymbolEqualityComparer.Default) == true) + // { + // return classDecl; + // } + // } + + // } + // } + // return null; + //} + + 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 && + ctor.ContainingType?.OriginalDefinition?.Equals(attributeType, SymbolEqualityComparer.Default) == true) + { + return classDecl; + } + } + return null; + } + + private static void GenerateCode( + Compilation compilation, + IEnumerable classes, + SourceProductionContext context) + { + var processedTypes = new HashSet(SymbolEqualityComparer.Default); + + + 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)) continue; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor( + "PA001", + "Generated Accessors", + $"Generating accessors for {classSymbol.Name}", + "Performance", + DiagnosticSeverity.Info, + true), + Location.None)); + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor("PA002", "Class Found", + $"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, true), + Location.None)); + + var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); + context.AddSource($"{classSymbol.Name}Extension.g.cs", SourceText.From(code, Encoding.UTF8)); + } + } + + private static string BuildAccessorsForType( + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet processedTypes) + { + var code = new StringBuilder(); + code.AppendLine("// "); + code.AppendLine("#nullable enable"); + code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); + code.AppendLine(); + + code.AppendLine($"public static class {classSymbol.Name}Extension{GetGenericParams(classSymbol)}"); + code.AppendLine("{"); + + foreach (var prop in classSymbol.GetMembers().OfType()) + { + if (prop.IsIndexer) continue; + + GeneratePropertyAccessors(prop, code, compilation, processedTypes); + } + + code.AppendLine("}"); + return code.ToString(); + } + + private static string GetGenericParams(INamedTypeSymbol symbol) + => symbol.IsGenericType ? $"<{string.Join(", ", symbol.TypeParameters.Select(t => t.Name))}>" : ""; + + private static void GeneratePropertyAccessors( + IPropertySymbol prop, + StringBuilder code, + Compilation compilation, + HashSet processedTypes) + { + // 关键修复点1:安全类型转换 + if (prop.Type is not ITypeSymbol propType) return; + + code.AppendLine($" // Processing property: {prop.Name}"); + + // 处理元组类型 + if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) + { + GenerateTupleAccessors(prop, tupleType, code); + } + else if (propType is INamedTypeSymbol namedType) + { + GenerateStandardAccessors(prop, namedType, code); + ProcessNestedType(namedType, compilation, processedTypes); + } + } + + private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) + { + var elements = tupleType.TupleElements; + var parentType = prop.ContainingType.ToDisplayString(); + + for (int i = 0; i < elements.Length; i++) + { + var element = elements[i]; + if (element.Type is not ITypeSymbol elementType) continue; + + var elementName = element.CorrespondingTupleField?.Name ?? $"Item{i + 1}"; + code.AppendLine($" public static {elementType.ToDisplayString()} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};"); + + if (prop.SetMethod != null) + { + var assignments = elements.Select((e, idx) => + idx == i ? "value" : $"obj.{prop.Name}.{e.Name}"); + code.AppendLine($" public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType.ToDisplayString()} value) => obj.{prop.Name} = ({string.Join(", ", assignments)});"); + } + } + } + + 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 void ProcessNestedType(ITypeSymbol typeSymbol, Compilation compilation, HashSet processedTypes) + { + if (typeSymbol is not INamedTypeSymbol namedType) return; + if (!ShouldProcessNestedType(namedType)) return; + if (!processedTypes.Add(namedType)) return; + + var code = BuildAccessorsForType(namedType, compilation, processedTypes); + } + + private static bool ShouldProcessNestedType(INamedTypeSymbol symbol) + { + return symbol.DeclaredAccessibility == Accessibility.Public && + !symbol.IsTupleType && + !symbol.IsAnonymousType && + !symbol.IsImplicitlyDeclared && + !symbol.Name.StartsWith("<"); + } + } +} \ No newline at end of file diff --git a/shared/JiShe.CollectBus.IncrementalGenerator/JiShe.CollectBus.IncrementalGenerator.csproj b/shared/JiShe.CollectBus.IncrementalGenerator/JiShe.CollectBus.IncrementalGenerator.csproj new file mode 100644 index 0000000..c36ce2b --- /dev/null +++ b/shared/JiShe.CollectBus.IncrementalGenerator/JiShe.CollectBus.IncrementalGenerator.csproj @@ -0,0 +1,14 @@ + + + + enable + netstandard2.0 + + true + latest + + + + + + diff --git a/shared/JiShe.CollectBus.SourceExtend/ComplexTypeSourceGenerator.cs b/shared/JiShe.CollectBus.SourceExtend/ComplexTypeSourceGenerator.cs deleted file mode 100644 index 352cd4a..0000000 --- a/shared/JiShe.CollectBus.SourceExtend/ComplexTypeSourceGenerator.cs +++ /dev/null @@ -1,187 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JiShe.CollectBus.SourceExtend -{ - /// - /// 复杂类型源生成器 - /// - [Generator] - public sealed class PropertyAccessorGenerator : IIncrementalGenerator - { - private const string AttributeName = "GenerateAccessors"; - - public void Initialize(IncrementalGeneratorInitializationContext context) - { - // 步骤1:筛选带有 [GenerateAccessors] 的类 - 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) - { - return node is ClassDeclarationSyntax { AttributeLists.Count: > 0 }; - } - - private static ClassDeclarationSyntax? GetClassDeclaration(GeneratorSyntaxContext context) - { - var classDecl = (ClassDeclarationSyntax)context.Node; - foreach (var attributeList in classDecl.AttributeLists) - { - foreach (var attribute in attributeList.Attributes) - { - var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; - if (symbol?.ContainingType.ToDisplayString() == $"{nameof(PropertyAccessorGenerator)}.{AttributeName}") - { - return classDecl; - } - } - } - return null; - } - - private static void GenerateCode( - Compilation compilation, - IEnumerable classes, - SourceProductionContext context) - { - var processedTypes = new HashSet(SymbolEqualityComparer.Default); - - foreach (var classDecl in classes.Distinct()) - { - var model = compilation.GetSemanticModel(classDecl.SyntaxTree); - var classSymbol = model.GetDeclaredSymbol(classDecl)!; - - if (!processedTypes.Add(classSymbol)) continue; - - var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); - context.AddSource($"{classSymbol.Name}Accessors.g.cs", code); - } - } - - private static string BuildAccessorsForType( - INamedTypeSymbol classSymbol, - Compilation compilation, - HashSet processedTypes) - { - var code = new StringBuilder(); - code.AppendLine("// "); - code.AppendLine("#nullable enable"); - code.AppendLine(); - code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); - code.AppendLine(); - - // 处理泛型参数 - var genericParams = classSymbol.IsGenericType - ? $"<{string.Join(", ", classSymbol.TypeParameters.Select(t => t.Name))}>" - : ""; - - code.AppendLine($"public static class {classSymbol.Name}Accessors{genericParams}"); - code.AppendLine("{"); - - foreach (var prop in classSymbol.GetMembers().OfType()) - { - if (prop.IsIndexer) continue; - - GeneratePropertyAccessors(prop, code, compilation, processedTypes); - } - - code.AppendLine("}"); - return code.ToString(); - } - - private static void GeneratePropertyAccessors( - IPropertySymbol prop, - StringBuilder code, - Compilation compilation, - HashSet processedTypes) - { - var propType = prop.Type; - var parentType = prop.ContainingType.ToDisplayString(); - - // 处理元组类型 - if (propType.IsTupleType && propType is INamedTypeSymbol tupleType) - { - GenerateTupleAccessors(prop, tupleType, code); - } - else if (propType is INamedTypeSymbol namedType) - { - GenerateStandardAccessors(prop, namedType, code); - ProcessNestedType(namedType, compilation, processedTypes); - } - } - - private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) - { - var elements = tupleType.TupleElements; - var parentType = prop.ContainingType.ToDisplayString(); - - for (int i = 0; i < elements.Length; i++) - { - var element = elements[i]; - var elementType = element.Type.ToDisplayString(); - var elementName = element.CorrespondingTupleField?.Name ?? $"Item{i + 1}"; - - code.AppendLine($" public static {elementType} Get{prop.Name}_{elementName}({parentType} obj)"); - code.AppendLine($" => obj.{prop.Name}.{elementName};"); - - if (prop.SetMethod != null) - { - var assignments = elements.Select((e, idx) => - idx == i ? "value" : $"obj.{prop.Name}.{e.Name}"); - - code.AppendLine($" public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value)"); - code.AppendLine($" => obj.{prop.Name} = ({string.Join(", ", assignments)});"); - } - } - } - - private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) - { - var typeName = propType.ToDisplayString(); - var parentType = prop.ContainingType.ToDisplayString(); - - code.AppendLine($" public static {typeName} Get{prop.Name}({parentType} obj)"); - code.AppendLine($" => obj.{prop.Name};"); - - if (prop.SetMethod != null) - { - code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {typeName} value)"); - code.AppendLine($" => obj.{prop.Name} = value;"); - } - } - - private static void ProcessNestedType(INamedTypeSymbol typeSymbol, Compilation compilation, HashSet processedTypes) - { - if (ShouldGenerateForType(typeSymbol) && processedTypes.Add(typeSymbol)) - { - var code = BuildAccessorsForType(typeSymbol, compilation, processedTypes); - // 注意:实际项目中需要通过 SourceProductionContext 添加源代码 - } - } - - private static bool ShouldGenerateForType(INamedTypeSymbol typeSymbol) - { - return !typeSymbol.IsTupleType && - !typeSymbol.IsAnonymousType && - !typeSymbol.IsNativeIntegerType && - typeSymbol.DeclaredAccessibility == Accessibility.Public && - !typeSymbol.Name.StartsWith("<"); - } - } -} \ No newline at end of file diff --git a/shared/JiShe.CollectBus.SourceExtend/JiShe.CollectBus.SourceExtend.csproj b/shared/JiShe.CollectBus.SourceExtend/JiShe.CollectBus.SourceExtend.csproj deleted file mode 100644 index a06bde8..0000000 --- a/shared/JiShe.CollectBus.SourceExtend/JiShe.CollectBus.SourceExtend.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - netstandard2.1 - 12.0 - enable - true - - - - - diff --git a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj index 4ebd67d..5501841 100644 --- a/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj +++ b/web/JiShe.CollectBus.Host/JiShe.CollectBus.Host.csproj @@ -5,7 +5,7 @@ enable enable True - + @@ -55,9 +55,9 @@ - - - + + +