From 53e6bb252ab74375010fbe6877ce5ced5590e47d Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Tue, 6 May 2025 23:46:12 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BF=AE=E5=A4=8D15=E5=88=86=E9=92=9F?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1Kafka=E4=B8=BB=E9=A2=98=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=A2=9E?= =?UTF-8?q?=E9=87=8F=E6=BA=90=E7=A0=81=E5=B7=A5=E5=8E=82=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 217 ++++++++++++++---- .../Samples/SampleAppService.cs | 5 + .../BasicScheduledMeterReadingService.cs | 2 +- ...rsProvider.cs => ISourceEntityAccessor.cs} | 4 +- 4 files changed, 178 insertions(+), 50 deletions(-) rename shared/JiShe.CollectBus.Analyzers.Shared/{ISourceAnalyzersProvider.cs => ISourceEntityAccessor.cs} (92%) diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 20951e5..8ec5eb9 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -14,17 +14,14 @@ namespace JiShe.CollectBus.IncrementalGenerator public class ComplexTypeSourceAnalyzers : IIncrementalGenerator { private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute"; + private const string SourceEntityAccessorFactoryNamespace = "JiShe.CollectBus.Analyzers.Shared"; public void Initialize(IncrementalGeneratorInitializationContext context) { //Debugger.Launch(); - context.RegisterPostInitializationOutput(ctx => - { - ctx.AddSource("GeneratorInit.g.cs", "// Initialization Marker"); - }); - // 步骤1:筛选带有 [GenerateAccessors] 的类 + // 步骤1:筛选带有 [SourceAnalyzers] 的类 var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (s, _) => IsClassWithAttribute(s), @@ -35,12 +32,11 @@ namespace JiShe.CollectBus.IncrementalGenerator var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); context.RegisterSourceOutput(compilationAndClasses, (spc, source) => - GenerateCode(source.Left, source.Right!, spc)); + 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; @@ -76,18 +72,24 @@ namespace JiShe.CollectBus.IncrementalGenerator } } + /// + /// 生成代码 + /// + /// + /// + /// 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", "No Targets", - "No classes with [GenerateAccessors] found", "Debug", DiagnosticSeverity.Warning, true), + new DiagnosticDescriptor("GEN002", "没有目标类", + "没有找到SourceAnalyzers标记的类", "Debug", DiagnosticSeverity.Warning, true), Location.None)); } @@ -99,46 +101,66 @@ namespace JiShe.CollectBus.IncrementalGenerator if (classSymbol == null || !processedTypes.Add(classSymbol)) { context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor("GEN003", "Invalid Symbol", - $"Class symbol is null for {classDecl.Identifier.Text}", "Error", DiagnosticSeverity.Error, true), + new DiagnosticDescriptor("GEN003", "无效符号", + $"类名称为{classDecl.Identifier.Text} 符号为空", "Error", DiagnosticSeverity.Error, true), Location.None)); 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( + // "PA001", + // "Generated Accessors", + // $"Generating accessors for {classSymbol.Name}", + // "Performance", + // DiagnosticSeverity.Info, + // true), + //Location.None)); - // 新增:输出继承链信息 - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy", - $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}", - "Debug", DiagnosticSeverity.Info, true), - Location.None)); + //// 新增:输出继承链信息 + //context.ReportDiagnostic(Diagnostic.Create( + // new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy", + // $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}", + // "Debug", DiagnosticSeverity.Info, true), + // Location.None)); - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor("PA002", "Class Found", - $"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, 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); - System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出 + //System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出 context.AddSource($"{classSymbol.Name}Extension.g.cs", code); + + + var code3 = BuildAccessorsForType2(classSymbol, compilation, processedTypes); + context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3); + + //code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); + //if (classSymbol.ContainingNamespace.ToDisplayString() == "JiShe.CollectBus.IoTDB") + //{ + + //} } + + // 生成工厂注册代码 + context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode()); } + /// + /// 构建类的属性访问器代码 + /// + /// + /// + /// + /// private static string BuildAccessorsForType( - INamedTypeSymbol classSymbol, - Compilation compilation, - HashSet processedTypes) + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet processedTypes) { var code = new StringBuilder(); code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); @@ -151,25 +173,67 @@ namespace JiShe.CollectBus.IncrementalGenerator 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); - //} - foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) { if (prop.IsIndexer) continue; - GeneratePropertyAccessors(prop, code, compilation, processedTypes); + GeneratePropertyAccessorsForType(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 string BuildAccessorsForType2( + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet processedTypes) + { + var code = new StringBuilder(); + code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); + code.AppendLine("// Generated code for " + classSymbol.Name); + code.AppendLine("// "); + code.AppendLine("#nullable enable"); + code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); + code.AppendLine(); + + code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>"); + code.AppendLine("{"); + + foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) + { + if (prop.IsIndexer) continue; + GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes); + } + + code.AppendLine("}"); + + //var code3 = $@" + // public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}> + // {{ + // public object GetPropertyValue({classSymbol.Name} entity, string propName) => propName switch + // {{ + // {GeneratePropertyCases(classSymbol)} + // _ => throw new ArgumentException(""无效属性名"") + // }}; + + // {GenerateTupleSupport(classSymbol)} + // }}"; + + return code.ToString(); + } + + /// + /// 获取泛型参数 + /// + /// + /// public static string GetGenericParams(INamedTypeSymbol symbol) { if (!symbol.IsGenericType) return ""; @@ -177,13 +241,20 @@ namespace JiShe.CollectBus.IncrementalGenerator return $"<{string.Join(", ", parameters)}>"; } - private static void GeneratePropertyAccessors( + /// + /// 生成属性访问器代码 + /// + /// + /// + /// + /// + private static void GeneratePropertyAccessorsForType( IPropertySymbol prop, StringBuilder code, Compilation compilation, HashSet processedTypes) { - // 关键修复点1:安全类型转换 + // 安全类型转换 if (prop.Type is not ITypeSymbol propType) return; code.AppendLine($" // Processing property: {prop.Name}"); @@ -200,6 +271,12 @@ namespace JiShe.CollectBus.IncrementalGenerator } } + /// + /// 处理元组类型 + /// + /// + /// + /// private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) { var elements = tupleType.TupleElements; @@ -222,6 +299,12 @@ namespace JiShe.CollectBus.IncrementalGenerator } } + /// + /// 生成标准属性的访问器 + /// + /// + /// + /// private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) { var parentType = prop.ContainingType.ToDisplayString(); @@ -233,6 +316,13 @@ namespace JiShe.CollectBus.IncrementalGenerator } } + + /// + /// 处理嵌套类型 + /// + /// + /// + /// private static void ProcessNestedType(ITypeSymbol typeSymbol, Compilation compilation, HashSet processedTypes) { if (typeSymbol is not INamedTypeSymbol namedType) return; @@ -242,6 +332,11 @@ namespace JiShe.CollectBus.IncrementalGenerator var code = BuildAccessorsForType(namedType, compilation, processedTypes); } + /// + /// 处理嵌套类型 + /// + /// + /// private static bool ShouldProcessNestedType(INamedTypeSymbol symbol) { return symbol.DeclaredAccessibility == Accessibility.Public && @@ -250,5 +345,33 @@ namespace JiShe.CollectBus.IncrementalGenerator !symbol.IsImplicitlyDeclared && !symbol.Name.StartsWith("<"); } + + /// + /// 生成扩展类工厂代码 + /// + /// + private static string BuildFactoryCode() + { + return """ + using System; + using System.Collections.Concurrent; + namespace JiShe.CollectBus.Analyzers.Shared; + public static class SourceEntityAccessorFactory + { + private static readonly ConcurrentDictionary _accessors = new(); + + public static ISourceEntityAccessor GetAccessor() + { + if (!_accessors.TryGetValue(typeof(T), out var accessor)) + { + accessor = Activator.CreateInstance( + Type.GetType($"{typeof(T).Namespace}.{typeof(T).Name}Accessor")!)!; + _accessors.TryAdd(typeof(T), accessor); + } + return (ISourceEntityAccessor)accessor!; + } + } + """; + } } } \ No newline at end of file diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index ea2415e..79f0244 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -53,6 +53,10 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task UseSessionPool(long testTime) { + var dataTime = DateTime.Now; + + List values = new List() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", }; + ElectricityMeterTreeModel meter = new ElectricityMeterTreeModel() { @@ -67,6 +71,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS Timestamps = testTime// DateTimeOffset.UtcNow.ToUnixTimeNanoseconds()//testTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), }; //ElectricityMeterTreeModelExtension.GetCurrent() + //SourceEntityAccessorFactory.SetCurrent(meter); await _iotDBProvider.InsertAsync(meter); } diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index 2104d28..47b8a99 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -262,7 +262,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading //_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); return; } - _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask)); + _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, tempTask)); }); } else if (meteryType == MeterTypeEnum.WaterMeter.ToString()) diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceAnalyzersProvider.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs similarity index 92% rename from shared/JiShe.CollectBus.Analyzers.Shared/ISourceAnalyzersProvider.cs rename to shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs index 905f0ef..3395239 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceAnalyzersProvider.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Text; -namespace JiShe.CollectBus.Analyzers +namespace JiShe.CollectBus.Analyzers.Shared { - public interface ISourceAnalyzersProvider + public interface ISourceEntityAccessor { /// /// 获取属性值 From bca72025586daaab407c258c6c240183f17cb031 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Wed, 7 May 2025 10:15:45 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=A2=9E=E9=87=8F=E6=BA=90=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 247 ++++++++++++------ .../Model/TableModelSingleMeasuringEntity.cs | 2 +- .../Model/TreeModelSingleMeasuringEntity.cs | 2 +- .../Samples/SampleAppService.cs | 2 + .../ISourceEntityAccessor.cs | 26 +- 5 files changed, 177 insertions(+), 102 deletions(-) diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 8ec5eb9..3b25aa0 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,7 +9,7 @@ using System.Text; namespace JiShe.CollectBus.IncrementalGenerator { /// - /// 复杂类型源生成器 + /// 复杂类型增量源生成器 /// [Generator(LanguageNames.CSharp)] public class ComplexTypeSourceAnalyzers : IIncrementalGenerator @@ -32,11 +33,11 @@ namespace JiShe.CollectBus.IncrementalGenerator var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect()); context.RegisterSourceOutput(compilationAndClasses, (spc, source) => - GenerateCode(source.Left, source.Right!, spc)); + 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; @@ -106,44 +107,14 @@ namespace JiShe.CollectBus.IncrementalGenerator Location.None)); 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("HIERARCHY", "Class Hierarchy", - // $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}", - // "Debug", 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); - - //System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出 + + var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); context.AddSource($"{classSymbol.Name}Extension.g.cs", code); - var code3 = BuildAccessorsForType2(classSymbol, compilation, processedTypes); + var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes); context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3); - - //code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); - //if (classSymbol.ContainingNamespace.ToDisplayString() == "JiShe.CollectBus.IoTDB") - //{ - - //} } // 生成工厂注册代码 @@ -183,52 +154,6 @@ namespace JiShe.CollectBus.IncrementalGenerator return code.ToString(); } - /// - /// 构建类的属性访问器代码 - /// - /// - /// - /// - /// - private static string BuildAccessorsForType2( - INamedTypeSymbol classSymbol, - Compilation compilation, - HashSet processedTypes) - { - var code = new StringBuilder(); - code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); - code.AppendLine("// Generated code for " + classSymbol.Name); - code.AppendLine("// "); - code.AppendLine("#nullable enable"); - code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); - code.AppendLine(); - - code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>"); - code.AppendLine("{"); - - foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) - { - if (prop.IsIndexer) continue; - GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes); - } - - code.AppendLine("}"); - - //var code3 = $@" - // public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}> - // {{ - // public object GetPropertyValue({classSymbol.Name} entity, string propName) => propName switch - // {{ - // {GeneratePropertyCases(classSymbol)} - // _ => throw new ArgumentException(""无效属性名"") - // }}; - - // {GenerateTupleSupport(classSymbol)} - // }}"; - - return code.ToString(); - } - /// /// 获取泛型参数 /// @@ -262,11 +187,11 @@ namespace JiShe.CollectBus.IncrementalGenerator // 处理元组类型 if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) { - GenerateTupleAccessors(prop, tupleType, code); + GenerateTupleAccessorsForType(prop, tupleType, code); } else if (propType is INamedTypeSymbol namedType) { - GenerateStandardAccessors(prop, namedType, code); + GenerateStandardAccessorsForType(prop, namedType, code); ProcessNestedType(namedType, compilation, processedTypes); } } @@ -277,7 +202,7 @@ namespace JiShe.CollectBus.IncrementalGenerator /// /// /// - private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) + private static void GenerateTupleAccessorsForType(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) { var elements = tupleType.TupleElements; var parentType = prop.ContainingType.ToDisplayString(); @@ -305,7 +230,7 @@ namespace JiShe.CollectBus.IncrementalGenerator /// /// /// - private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) + private static void GenerateStandardAccessorsForType(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};"); @@ -316,7 +241,7 @@ namespace JiShe.CollectBus.IncrementalGenerator } } - + /// /// 处理嵌套类型 /// @@ -373,5 +298,153 @@ namespace JiShe.CollectBus.IncrementalGenerator } """; } + + /// + /// 构建实体类的源属性访问器代码 + /// + /// + /// + /// + /// + private static string BuildAccessorsForSourceEntity( + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet processedTypes) + { + var code = new StringBuilder(); + code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); + code.AppendLine("// Generated code for " + classSymbol.Name); + code.AppendLine("// "); + code.AppendLine("#nullable enable"); + code.AppendLine("using System;"); + code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;"); + code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};"); + code.AppendLine(); + + code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>"); + code.AppendLine("{"); + + GetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol); + + SetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol); + + code.AppendLine("}"); + + return code.ToString(); + } + + private static void GetGeneratePropertyValueForSourceEntity(IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) + { + + code.AppendLine($" public object GetPropertyValue({classSymbol.Name} targetEntity, string propertyName)"); + code.AppendLine(" {"); + code.AppendLine(" return propertyName switch"); + code.AppendLine(" {"); + + // 遍历所有属性 + foreach (var property in propList) + { + // 安全类型转换 + if (property.Type is not ITypeSymbol propType) continue; + + // 处理元组类型 + if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) + { + } + else if (propType is INamedTypeSymbol namedType) + { + // 生成属性访问的 + code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Get{property.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.Name} targetEntity, string propertyName, object value)"); + code.AppendLine(" {"); + code.AppendLine(" return propertyName switch"); + code.AppendLine(" {"); + + // 遍历所有属性 + foreach (var property in propList) + { + // 安全类型转换 + if (property.Type is not ITypeSymbol propType) continue; + + // 处理元组类型 + if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) + { + } + else if (propType is INamedTypeSymbol namedType) + { + // 生成属性设置赋值 + code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Set{property.Name}(targetEntity,({namedType.ToDisplayString()})value),"); + + } + } + + + code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")"); + code.AppendLine(" };"); + code.AppendLine(" }"); + } + + /// + /// 处理元组类型 + /// + /// + /// + /// + private static void GenerateTupleAccessorsForSourceEntity(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 GenerateStandardAccessorsForSourceEntity(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) + { + var parentType = prop.ContainingType.ToDisplayString(); + code.AppendLine($" public object {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;"); + } + } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index 966f226..3355a33 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -8,7 +8,7 @@ namespace JiShe.CollectBus.IoTDB.Model /// Table模型单项数据实体 /// [EntityType(EntityTypeEnum.TableModel)] - [SourceAnalyzers] + //[SourceAnalyzers] public class TableModelSingleMeasuringEntity : IoTEntity { /// diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs index 719c3c3..f59f648 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs @@ -8,7 +8,7 @@ namespace JiShe.CollectBus.IoTDB.Model /// Tree模型单项数据实体 /// [EntityType(EntityTypeEnum.TreeModel)] - [SourceAnalyzers] + //[SourceAnalyzers] public class TreeModelSingleMeasuringEntity : IoTEntity { /// diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index 79f0244..95ed072 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -72,6 +72,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS }; //ElectricityMeterTreeModelExtension.GetCurrent() //SourceEntityAccessorFactory.SetCurrent(meter); + + ElectricityMeterTreeModelAccessor await _iotDBProvider.InsertAsync(meter); } diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs index 3395239..2a448c1 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -22,19 +22,19 @@ namespace JiShe.CollectBus.Analyzers.Shared /// void SetPropertyValue(T entity, string propertyName, object value); - /// - /// 判断是否是元组属性 - /// - /// - /// - bool IsTupleProperty(string propertyName); + ///// + ///// 判断是否是元组属性 + ///// + ///// + ///// + //bool IsTupleProperty(string propertyName); - /// - /// 获取元组属性值 - /// - /// - /// - /// - (object Item1, object Item2) GetTupleParts(T entity, string tuplePropertyName); + ///// + ///// 获取元组属性值 + ///// + ///// + ///// + ///// + //(object Item1, object Item2) GetTupleParts(T entity, string tuplePropertyName); } } From 6b012d93037b5c251807dbe5520afaed3d277f56 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Wed, 7 May 2025 16:37:26 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=A2=9E=E9=87=8F=E6=BA=90=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 526 +++++++++--------- .../Model/TableModelSingleMeasuringEntity.cs | 4 +- .../Model/TreeModelSingleMeasuringEntity.cs | 4 +- .../Provider/IoTDBProvider.cs | 132 +++-- .../AnalysisData/DataStorage.cs | 4 +- .../Samples/SampleAppService.cs | 19 +- .../BasicScheduledMeterReadingService.cs | 68 +-- .../Ammeters/ElectricityMeter.cs | 2 +- .../Ammeters/ElectricityMeterTreeModel.cs | 3 + .../ISourceEntityAccessor.cs | 18 +- 10 files changed, 401 insertions(+), 379 deletions(-) diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 3b25aa0..804b7c0 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -15,13 +15,11 @@ namespace JiShe.CollectBus.IncrementalGenerator public class ComplexTypeSourceAnalyzers : IIncrementalGenerator { private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute"; - private const string SourceEntityAccessorFactoryNamespace = "JiShe.CollectBus.Analyzers.Shared"; public void Initialize(IncrementalGeneratorInitializationContext context) { //Debugger.Launch(); - // 步骤1:筛选带有 [SourceAnalyzers] 的类 var classDeclarations = context.SyntaxProvider .CreateSyntaxProvider( @@ -108,11 +106,6 @@ namespace JiShe.CollectBus.IncrementalGenerator continue; } - var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); - - context.AddSource($"{classSymbol.Name}Extension.g.cs", code); - - var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes); context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3); } @@ -120,40 +113,7 @@ namespace JiShe.CollectBus.IncrementalGenerator // 生成工厂注册代码 context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode()); } - - /// - /// 构建类的属性访问器代码 - /// - /// - /// - /// - /// - private static string BuildAccessorsForType( - INamedTypeSymbol classSymbol, - Compilation compilation, - HashSet processedTypes) - { - var code = new StringBuilder(); - code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); - code.AppendLine("// Generated code for " + classSymbol.Name); - 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 GetAllPropertiesInHierarchy(classSymbol)) - { - if (prop.IsIndexer) continue; - GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes); - } - - code.AppendLine("}"); - return code.ToString(); - } - + /// /// 获取泛型参数 /// @@ -165,72 +125,15 @@ namespace JiShe.CollectBus.IncrementalGenerator var parameters = symbol.TypeParameters.Select(t => t.Name); return $"<{string.Join(", ", parameters)}>"; } - - /// - /// 生成属性访问器代码 - /// - /// - /// - /// - /// - private static void GeneratePropertyAccessorsForType( - IPropertySymbol prop, - StringBuilder code, - Compilation compilation, - HashSet processedTypes) - { - // 安全类型转换 - if (prop.Type is not ITypeSymbol propType) return; - - code.AppendLine($" // Processing property: {prop.Name}"); - - // 处理元组类型 - if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) - { - GenerateTupleAccessorsForType(prop, tupleType, code); - } - else if (propType is INamedTypeSymbol namedType) - { - GenerateStandardAccessorsForType(prop, namedType, code); - ProcessNestedType(namedType, compilation, processedTypes); - } - } - - /// - /// 处理元组类型 - /// - /// - /// - /// - private static void GenerateTupleAccessorsForType(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 GenerateStandardAccessorsForType(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) + 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};"); @@ -240,211 +143,318 @@ namespace JiShe.CollectBus.IncrementalGenerator 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("<"); - } - - /// - /// 生成扩展类工厂代码 - /// - /// - private static string BuildFactoryCode() - { - return """ - using System; - using System.Collections.Concurrent; - namespace JiShe.CollectBus.Analyzers.Shared; - public static class SourceEntityAccessorFactory - { - private static readonly ConcurrentDictionary _accessors = new(); - - public static ISourceEntityAccessor GetAccessor() - { - if (!_accessors.TryGetValue(typeof(T), out var accessor)) - { - accessor = Activator.CreateInstance( - Type.GetType($"{typeof(T).Namespace}.{typeof(T).Name}Accessor")!)!; - _accessors.TryAdd(typeof(T), accessor); - } - return (ISourceEntityAccessor)accessor!; - } - } - """; - } - - /// - /// 构建实体类的源属性访问器代码 - /// - /// - /// - /// - /// private static string BuildAccessorsForSourceEntity( - INamedTypeSymbol classSymbol, - Compilation compilation, - HashSet processedTypes) + INamedTypeSymbol classSymbol, + Compilation compilation, + HashSet processedTypes) { var code = new StringBuilder(); - code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); - code.AppendLine("// Generated code for " + classSymbol.Name); 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(); - code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>"); - code.AppendLine("{"); - - GetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol); + // 处理泛型类型参数 + 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); + - SetGeneratePropertyValueForSourceEntity(GetAllPropertiesInHierarchy(classSymbol), code, compilation, classSymbol); code.AppendLine("}"); - return code.ToString(); } - private static void GetGeneratePropertyValueForSourceEntity(IEnumerable propList, + /// + /// 生成泛型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.Name} targetEntity, string propertyName)"); + code.AppendLine($" public object GetPropertyValue({classSymbol} targetEntity, string propertyName)"); + code.AppendLine(" {"); + code.AppendLine(" return propertyName switch"); code.AppendLine(" {"); - code.AppendLine(" return propertyName switch"); - code.AppendLine(" {"); - // 遍历所有属性 - foreach (var property in propList) - { - // 安全类型转换 - if (property.Type is not ITypeSymbol propType) continue; - - // 处理元组类型 - if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) - { - } - else if (propType is INamedTypeSymbol namedType) - { - // 生成属性访问的 - code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Get{property.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.Name} targetEntity, string propertyName, object value)"); - code.AppendLine(" {"); - code.AppendLine(" return propertyName switch"); - code.AppendLine(" {"); - - // 遍历所有属性 - foreach (var property in propList) + foreach (var prop in propList) { - // 安全类型转换 - if (property.Type is not ITypeSymbol propType) continue; - - // 处理元组类型 - if (propType is INamedTypeSymbol { IsTupleType: true } tupleType) - { - } - else if (propType is INamedTypeSymbol namedType) + if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { - // 生成属性设置赋值 - code.AppendLine($" \"{property.Name}\" => {classSymbol.Name}Extension.Set{property.Name}(targetEntity,({namedType.ToDisplayString()})value),"); - - } + 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(" }"); + code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")"); + code.AppendLine(" };"); + code.AppendLine(" }"); } /// - /// 处理元组类型 + /// 属性设置生成逻辑 /// - /// - /// + /// 属性集合 /// - private static void GenerateTupleAccessorsForSourceEntity(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) + /// + /// + private static void SetGeneratePropertyValueForSourceEntity( + IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) { - var elements = tupleType.TupleElements; - var parentType = prop.ContainingType.ToDisplayString(); + code.AppendLine($" public void SetPropertyValue({classSymbol} targetEntity, string propertyName, object value)"); + code.AppendLine(" {"); + code.AppendLine(" switch (propertyName)"); + code.AppendLine(" {"); - for (int i = 0; i < elements.Length; i++) + foreach (var prop in propList) { - 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) + if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { - 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)});"); + 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 GenerateStandardAccessorsForSourceEntity(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) + /// + /// + private static void GeneratePropertyListForSourceEntity( + IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) { - var parentType = prop.ContainingType.ToDisplayString(); - code.AppendLine($" public object {propType.ToDisplayString()} Get{prop.Name}({parentType} obj) => obj.{prop.Name};"); - - if (prop.SetMethod != null) + code.AppendLine(" public List PropertyList {get;} = new List()"); + code.AppendLine(" {"); + List tempPropList = new List(); + foreach (var prop in propList) { - code.AppendLine($" public static void Set{prop.Name}({parentType} obj, {propType.ToDisplayString()} value) => obj.{prop.Name} = value;"); + 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(" };"); } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index 3355a33..ed0fd4d 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -8,13 +8,13 @@ namespace JiShe.CollectBus.IoTDB.Model /// Table模型单项数据实体 /// [EntityType(EntityTypeEnum.TableModel)] - //[SourceAnalyzers] + [SourceAnalyzers] public class TableModelSingleMeasuringEntity : IoTEntity { /// /// 单项数据键值对 /// [SingleMeasuring(nameof(SingleColumn))] - public required Tuple SingleColumn { get; set; } + public required ValueTuple SingleColumn { get; set; } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs index f59f648..c87516c 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs @@ -8,13 +8,13 @@ namespace JiShe.CollectBus.IoTDB.Model /// Tree模型单项数据实体 /// [EntityType(EntityTypeEnum.TreeModel)] - //[SourceAnalyzers] + [SourceAnalyzers] public class TreeModelSingleMeasuringEntity : IoTEntity { /// /// 单项数据键值对 /// [SingleMeasuring(nameof(SingleMeasuring))] - public required Tuple SingleMeasuring { get; set; } + public required ValueTuple SingleMeasuring { get; set; } } } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs index d867674..aebce66 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs @@ -20,6 +20,7 @@ using JiShe.CollectBus.IoTDB.Options; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities; +using JiShe.CollectBus.Analyzers.Shared; namespace JiShe.CollectBus.IoTDB.Provider { @@ -176,6 +177,8 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public async Task GetMetadata() where T : IoTEntity { + var accessor = SourceEntityAccessorFactory.GetAccessor(); + var columns = CollectColumnMetadata(typeof(T)); var metadata = BuildDeviceMetadata(columns); var metaData = MetadataCache.AddOrUpdate( @@ -260,6 +263,8 @@ namespace JiShe.CollectBus.IoTDB.Provider List tempColumnNames = new List(); tempColumnNames.AddRange(metadata.ColumnNames); + var accessor = SourceEntityAccessorFactory.GetAccessor(); + var entityTypeAttribute = typeof(T).GetCustomAttribute(); if (entityTypeAttribute == null) @@ -295,69 +300,74 @@ namespace JiShe.CollectBus.IoTDB.Provider foreach (var measurement in tempColumnNames) { - - PropertyInfo propertyInfo = typeof(T).GetProperty(measurement); - if (propertyInfo == null) - { - throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,没有找到{measurement}属性,属于异常情况,-101。"); - } - - var value = propertyInfo.GetValue(entity); - if (propertyInfo.IsDefined(typeof(SingleMeasuringAttribute), false) && metadata.IsSingleMeasuring == true)//表示当前对象是单测点模式 - { - if (value != null) - { - Type tupleType = value.GetType(); - Type[] tupleArgs = tupleType.GetGenericArguments(); - Type item2Type = tupleArgs[1]; // T 的实际类型 - var item1 = tupleType.GetProperty("Item1")!.GetValue(value); - var item2 = tupleType.GetProperty("Item2")!.GetValue(value); - if (item1 == null || item2 == null) - { - throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,单测点模式构建失败,没有获取测点名称或者测点值,-102。"); - } - - var indexOf = metadata.ColumnNames.IndexOf(measurement); - metadata.ColumnNames[indexOf] = (string)item1!; - - rowValues.Add(item2); - } - else - { - rowValues.Add(null); - } - - //同时如果是单测点模式,且是table模型存储,路径只能通过DevicePathBuilder.GetDeviceTableName(entity)获取 - if (_runtimeContext.UseTableSessionPool) - { - tableNameOrTreePath = DevicePathBuilder.GetDeviceTableName(entity); - } - } - else - { - - //需要根据value的类型,进行相应的值映射转换,例如datetime转换为long的时间戳值 - if (value != null) - { - Type tupleType = value.GetType(); - var tempValue = tupleType.Name.ToUpper() switch - { - "DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(), - _ => value - }; - - rowValues.Add(tempValue); - } - else - { - rowValues.Add(value); - } - - } - + rowValues.Add(accessor.GetPropertyValue(entity,measurement)); } - values.Add(rowValues); + //foreach (var measurement in tempColumnNames) + //{ + + // PropertyInfo propertyInfo = typeof(T).GetProperty(measurement); + // if (propertyInfo == null) + // { + // throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,没有找到{measurement}属性,属于异常情况,-101。"); + // } + + // var value = propertyInfo.GetValue(entity); + // if (propertyInfo.IsDefined(typeof(SingleMeasuringAttribute), false) && metadata.IsSingleMeasuring == true)//表示当前对象是单测点模式 + // { + // if (value != null) + // { + // Type tupleType = value.GetType(); + // Type[] tupleArgs = tupleType.GetGenericArguments(); + // Type item2Type = tupleArgs[1]; // T 的实际类型 + // var item1 = tupleType.GetProperty("Item1")!.GetValue(value); + // var item2 = tupleType.GetProperty("Item2")!.GetValue(value); + // if (item1 == null || item2 == null) + // { + // throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时,单测点模式构建失败,没有获取测点名称或者测点值,-102。"); + // } + + // var indexOf = metadata.ColumnNames.IndexOf(measurement); + // metadata.ColumnNames[indexOf] = (string)item1!; + + // rowValues.Add(item2); + // } + // else + // { + // rowValues.Add(null); + // } + + // //同时如果是单测点模式,且是table模型存储,路径只能通过DevicePathBuilder.GetDeviceTableName(entity)获取 + // if (_runtimeContext.UseTableSessionPool) + // { + // tableNameOrTreePath = DevicePathBuilder.GetDeviceTableName(entity); + // } + // } + // else + // { + + // //需要根据value的类型,进行相应的值映射转换,例如datetime转换为long的时间戳值 + // if (value != null) + // { + // Type tupleType = value.GetType(); + // var tempValue = tupleType.Name.ToUpper() switch + // { + // "DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(), + // _ => value + // }; + + // rowValues.Add(tempValue); + // } + // else + // { + // rowValues.Add(value); + // } + + // } + + //} + + values.Add(rowValues); //如果指定了路径 if (!string.IsNullOrWhiteSpace(tableNameOrTreePath)) diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs index 00435e0..3b3816a 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs @@ -90,7 +90,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceType = $"{data.MeterType}", ProjectId = $"{data.ProjectId}", Timestamps = data.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(data.FiledName ?? string.Empty, data.DataValue ?? default) + SingleMeasuring = (data.FiledName ?? string.Empty, data.DataValue ?? default) }; _runtimeContext.UseTableSessionPool = true; // 使用表模型池 var taskSendInfo = await _dbProvider.QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); @@ -193,7 +193,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData DeviceType = $"{item.MeterType}", ProjectId = $"{item.ProjectId}", Timestamps = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeMilliseconds(), // TODO:这里暂时格式化15分钟数据,需要进行调整 - SingleMeasuring = new Tuple(item.FiledName ?? string.Empty, item.DataValue ?? default) + SingleMeasuring = (item.FiledName ?? string.Empty, item.DataValue ?? default) }; _runtimeContext.UseTableSessionPool = true; // 使用表模型池 var taskSendInfo = await _dbProvider.QueryAsync(new IoTDBQueryOptions() { TableNameOrTreePath = DevicePathBuilder.GetTableName(), Conditions = conditions, PageIndex = 0, PageSize = 1 }); diff --git a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs index 95ed072..ef3b894 100644 --- a/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs +++ b/services/JiShe.CollectBus.Application/Samples/SampleAppService.cs @@ -73,7 +73,9 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS //ElectricityMeterTreeModelExtension.GetCurrent() //SourceEntityAccessorFactory.SetCurrent(meter); - ElectricityMeterTreeModelAccessor + //ElectricityMeterTreeModelAccessor. + //TableModelSingleMeasuringEntityExtension + //TableModelSingleMeasuringEntityAccessor.GetSystemName(meter); await _iotDBProvider.InsertAsync(meter); } @@ -172,6 +174,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity(string measuring, string value, DateTime time) { + time = DateTime.Now; + var meter = new TreeModelSingleMeasuringEntity() { SystemName = "energy", @@ -179,7 +183,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "1", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(measuring, value) + SingleMeasuring = (measuring, value) }; await _iotDBProvider.InsertAsync(meter); } @@ -192,6 +196,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTreeModelSingleMeasuringEntity2(string measuring, int value, DateTime time) { + time = DateTime.Now; var meter = new TreeModelSingleMeasuringEntity() { SystemName = "energy", @@ -199,7 +204,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleMeasuring = new Tuple(measuring, value) + SingleMeasuring = (measuring, value) }; await _iotDBProvider.InsertAsync(meter); } @@ -212,6 +217,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTableModelSingleMeasuringEntity(string measuring, string value, DateTime time) { + time = DateTime.Now; + var meter = new TableModelSingleMeasuringEntity() { SystemName = "energy", @@ -219,7 +226,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleColumn = new Tuple(measuring, value) + SingleColumn = (measuring, value) }; _dbContext.UseTableSessionPool = true; await _iotDBProvider.InsertAsync(meter); @@ -233,6 +240,8 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS [HttpGet] public async Task TestTableModelSingleMeasuringEntity2(string measuring, int value, DateTime time) { + time = DateTime.Now; + var meter = new TableModelSingleMeasuringEntity() { SystemName = "energy", @@ -240,7 +249,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS DeviceType = "Ammeter", ProjectId = "10059", Timestamps = time.GetDateTimeOffset().ToUnixTimeMilliseconds(), - SingleColumn = new Tuple(measuring, value) + SingleColumn = (measuring, value) }; _dbContext.UseTableSessionPool = true; await _iotDBProvider.InsertAsync(meter); diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index 47b8a99..e75ad84 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -336,47 +336,47 @@ namespace JiShe.CollectBus.ScheduledMeterReading //此处代码不要删除 #if DEBUG - var timeDensity = "15"; - var serverTagName = "JiSheCollectBus2"; - var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var timeDensity = "15"; + //var serverTagName = "JiSheCollectBus2"; + //var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + //var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; List meterInfos = new List(); - List focusAddressDataLista = new List(); - var timer1 = Stopwatch.StartNew(); + //List focusAddressDataLista = new List(); + //var timer1 = Stopwatch.StartNew(); - var allIds = new HashSet(); - decimal? score = null; - string member = null; + //var allIds = new HashSet(); + //decimal? score = null; + //string member = null; - while (true) - { - var page = await _redisDataCacheService.GetAllPagedData( - redisCacheMeterInfoHashKeyTemp, - redisCacheMeterInfoZSetScoresIndexKeyTemp, - pageSize: 1000, - lastScore: score, - lastMember: member); + //while (true) + //{ + // var page = await _redisDataCacheService.GetAllPagedData( + // redisCacheMeterInfoHashKeyTemp, + // redisCacheMeterInfoZSetScoresIndexKeyTemp, + // pageSize: 1000, + // lastScore: score, + // lastMember: member); - meterInfos.AddRange(page.Items); - focusAddressDataLista.AddRange(page.Items.Select(d => $"{d.MeterId}")); - foreach (var item in page.Items) - { - if (!allIds.Add(item.MemberId)) - { - _logger.LogError($"{item.MemberId}Duplicate data found!"); - } - } - if (!page.HasNext) break; - score = page.NextScore; - member = page.NextMember; - } + // meterInfos.AddRange(page.Items); + // focusAddressDataLista.AddRange(page.Items.Select(d => $"{d.MeterId}")); + // foreach (var item in page.Items) + // { + // if (!allIds.Add(item.MemberId)) + // { + // _logger.LogError($"{item.MemberId}Duplicate data found!"); + // } + // } + // if (!page.HasNext) break; + // score = page.NextScore; + // member = page.NextMember; + //} - timer1.Stop(); - _logger.LogError($"电表初始化读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); - DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); + //timer1.Stop(); + //_logger.LogError($"电表初始化读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); + //DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); return; #else var meterInfos = await GetAmmeterInfoList(gatherCode); diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs index 9ba3c94..c04a554 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs @@ -6,7 +6,7 @@ using JiShe.CollectBus.IoTDB.Model; namespace JiShe.CollectBus.Ammeters { [EntityType(EntityTypeEnum.TableModel)] - [SourceAnalyzers] + //[SourceAnalyzers] public class ElectricityMeter : IoTEntity { [ATTRIBUTEColumn] diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs index 1f11198..38d3ee6 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs @@ -2,6 +2,7 @@ using JiShe.CollectBus.IoTDB.Attribute; using JiShe.CollectBus.IoTDB.Enums; using JiShe.CollectBus.IoTDB.Model; +using System; namespace JiShe.CollectBus.Ammeters { @@ -35,5 +36,7 @@ namespace JiShe.CollectBus.Ammeters [FIELDColumn] public double? Currentd { get; set; } + + public Tuple TupleData { get; set;} } } diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs index 2a448c1..baff180 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -22,19 +22,9 @@ namespace JiShe.CollectBus.Analyzers.Shared /// void SetPropertyValue(T entity, string propertyName, object value); - ///// - ///// 判断是否是元组属性 - ///// - ///// - ///// - //bool IsTupleProperty(string propertyName); - - ///// - ///// 获取元组属性值 - ///// - ///// - ///// - ///// - //(object Item1, object Item2) GetTupleParts(T entity, string tuplePropertyName); + /// + /// 属性名称集合 + /// + List PropertyList { get; } } } From ff517664fe1091c8011f0432f11192722c654be4 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Wed, 7 May 2025 17:20:10 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E5=A4=8D=E6=9D=82=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=A2=9E=E9=87=8F=E6=BA=90=E7=94=9F=E6=88=90=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 46 +++++++---- ...TableModelSingleMeasuringEntityAccessor.cs | 77 +++++++++++++++++++ .../Provider/IoTDBProvider.cs | 9 ++- 3 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 804b7c0..195175a 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -162,13 +162,19 @@ namespace JiShe.CollectBus.IncrementalGenerator 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( - $"public sealed class {classSymbol.Name}Accessor{genericParams} " + + $"{accessibility} sealed class {classSymbol.Name}Accessor{genericParams} " + // 保留泛型参数 $": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>"); code.AppendLine("{"); @@ -306,26 +312,32 @@ namespace JiShe.CollectBus.IncrementalGenerator 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) + // 获取泛型类型定义信息(如果是泛型类型) + 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"); - - return t.IsGenericType - ? Activator.CreateInstance(type.MakeGenericType(t.GetGenericArguments())) - : Activator.CreateInstance(type); + + // 处理泛型参数 + if (isGeneric && accessorType.IsGenericTypeDefinition) + { + accessorType = accessorType.MakeGenericType(t.GetGenericArguments()); + } + + return Activator.CreateInstance(accessorType)!; }); } } diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs new file mode 100644 index 0000000..9c9c773 --- /dev/null +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs @@ -0,0 +1,77 @@ +// +#nullable enable +using System; +using System.Collections.Generic; +using JiShe.CollectBus.Analyzers.Shared; +namespace JiShe.CollectBus.IoTDB.Model; + +public sealed class TableModelSingleMeasuringEntityAccessor3 : ISourceEntityAccessor> +{ + public static string GetSingleColumn_Item1(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj) => obj.SingleColumn.Item1; + public static void SetSingleColumn_Item1(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj, string value) => obj.SingleColumn = (value, obj.SingleColumn.Item2); + public static T GetSingleColumn_Item2(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj) => obj.SingleColumn.Item2; + public static void SetSingleColumn_Item2(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj, T value) => obj.SingleColumn = (obj.SingleColumn.Item1, value); + public static string GetSystemName(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.SystemName; + public static void SetSystemName(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.SystemName = value; + public static string GetProjectId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.ProjectId; + public static void SetProjectId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.ProjectId = value; + public static string GetDeviceType(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.DeviceType; + public static void SetDeviceType(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.DeviceType = value; + public static string GetDeviceId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.DeviceId; + public static void SetDeviceId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.DeviceId = value; + public static long GetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.Timestamps; + public static void SetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, long value) => obj.Timestamps = value; + public List PropertyList { get; } = new List() + { +"SingleColumn.Item1","SingleColumn.Item2","SystemName","ProjectId","DeviceType","DeviceId","Timestamps" }; + public object GetPropertyValue(JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity targetEntity, string propertyName) + { + return propertyName switch + { + "SingleColumn.Item1" => GetSingleColumn_Item1(targetEntity), + "SingleColumn.Item2" => GetSingleColumn_Item2(targetEntity), + "SystemName" => GetSystemName(targetEntity), + "ProjectId" => GetProjectId(targetEntity), + "DeviceType" => GetDeviceType(targetEntity), + "DeviceId" => GetDeviceId(targetEntity), + "Timestamps" => GetTimestamps(targetEntity), + _ => throw new ArgumentException($"Unknown property: {propertyName}") + }; + } + public void SetPropertyValue(JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity targetEntity, string propertyName, object value) + { + switch (propertyName) + { + case "SingleColumn.Item1": + SetSingleColumn_Item1( + targetEntity, (string)value); + break; + case "SingleColumn.Item2": + SetSingleColumn_Item2( + targetEntity, (T)value); + break; + case "SystemName": + SetSystemName( + targetEntity, (string)value); + break; + case "ProjectId": + SetProjectId( + targetEntity, (string)value); + break; + case "DeviceType": + SetDeviceType( + targetEntity, (string)value); + break; + case "DeviceId": + SetDeviceId( + targetEntity, (string)value); + break; + case "Timestamps": + SetTimestamps( + targetEntity, (long)value); + break; + default: + throw new ArgumentException($"Unknown property: {propertyName}"); + } + } +} diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs index aebce66..704363c 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs @@ -566,6 +566,8 @@ namespace JiShe.CollectBus.IoTDB.Provider //metadata.ColumnNames.Insert(0, "Timestamps"); //metadata.DataTypes.Insert(0, TSDataType.TIMESTAMP); + var accessor = SourceEntityAccessorFactory.GetAccessor(); + while (dataSet.HasNext() && results.Count < pageSize) { var record = dataSet.Next(); @@ -588,11 +590,14 @@ namespace JiShe.CollectBus.IoTDB.Provider if (measurement.ToLower().EndsWith("time")) { - typeof(T).GetProperty(measurement)?.SetValue(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); + //typeof(T).GetProperty(measurement)?.SetValue(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); + + accessor.SetPropertyValue(entity, measurement, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); } else { - typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue); + accessor.SetPropertyValue(entity, measurement, tempValue); + //typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue); } } From c47ee9446900e4f2c76baa3ec64fc522c6a35220 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Wed, 7 May 2025 17:27:37 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 51 +++++++++++++++++-- ...TableModelSingleMeasuringEntityAccessor.cs | 2 +- .../ISourceEntityAccessor.cs | 8 ++- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 195175a..ea0ef13 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -157,6 +157,7 @@ namespace JiShe.CollectBus.IncrementalGenerator 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()};"); @@ -198,7 +199,14 @@ namespace JiShe.CollectBus.IncrementalGenerator //生成当前类属性名称集合 GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol); - + + //生成当前类属性信息集合 + GeneratePropertyInfoListForSourceEntity( + propList, + code, + compilation, + classSymbol); + //生成当前类属性访问 GetGeneratePropertyValueForSourceEntity( @@ -213,9 +221,7 @@ namespace JiShe.CollectBus.IncrementalGenerator code, compilation, classSymbol); - - - + code.AppendLine("}"); return code.ToString(); } @@ -468,5 +474,42 @@ namespace JiShe.CollectBus.IncrementalGenerator code.AppendLine(" };"); } + + + /// + /// 生成当前类属性信息集合 + /// + /// 属性集合 + /// + /// + /// + private static void GeneratePropertyInfoListForSourceEntity( + 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(" };"); + } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs index 9c9c773..e0bedd4 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs @@ -21,7 +21,7 @@ public sealed class TableModelSingleMeasuringEntityAccessor3 : ISourceEntityA public static void SetDeviceId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.DeviceId = value; public static long GetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.Timestamps; public static void SetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, long value) => obj.Timestamps = value; - public List PropertyList { get; } = new List() + public List PropertyNameList { get; } = new List() { "SingleColumn.Item1","SingleColumn.Item2","SystemName","ProjectId","DeviceType","DeviceId","Timestamps" }; public object GetPropertyValue(JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity targetEntity, string propertyName) diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs index baff180..5e67826 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Text; namespace JiShe.CollectBus.Analyzers.Shared @@ -25,6 +26,11 @@ namespace JiShe.CollectBus.Analyzers.Shared /// /// 属性名称集合 /// - List PropertyList { get; } + List PropertyNameList { get; } + + /// + /// 属性信息集合 + /// + List PropertyInfoList { get; } } } From f71ce3bacb65b20da327a280fcab856da8596d30 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Thu, 8 May 2025 08:43:37 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E6=BA=90=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComplexTypeSourceAnalyzers.cs | 44 +++++++---- ...TableModelSingleMeasuringEntityAccessor.cs | 77 ------------------- .../T37612012ProtocolPlugin.cs | 16 ++-- .../DataChannels/DataChannelManageService.cs | 14 ++-- .../BasicScheduledMeterReadingService.cs | 68 ++++++++-------- 5 files changed, 78 insertions(+), 141 deletions(-) delete mode 100644 modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index ea0ef13..3b82bf2 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -452,7 +452,7 @@ namespace JiShe.CollectBus.IncrementalGenerator Compilation compilation, INamedTypeSymbol classSymbol) { - code.AppendLine(" public List PropertyList {get;} = new List()"); + code.AppendLine(" public List PropertyNameList {get;} = new List()"); code.AppendLine(" {"); List tempPropList = new List(); foreach (var prop in propList) @@ -477,39 +477,53 @@ namespace JiShe.CollectBus.IncrementalGenerator /// - /// 生成当前类属性信息集合 + /// 生成当前类属性信息集合(支持嵌套元组) /// - /// 属性集合 - /// - /// - /// private static void GeneratePropertyInfoListForSourceEntity( IEnumerable propList, StringBuilder code, Compilation compilation, INamedTypeSymbol classSymbol) { - code.AppendLine(" public List PropertyList {get;} = new List()"); + code.AppendLine(" public List PropertyInfoList { get; } = new List"); code.AppendLine(" {"); - List tempPropList = new List(); + + var initializerLines = new List(); + foreach (var prop in propList) { + // 主属性 + AddPropertyInitializer(classSymbol, prop, initializerLines); + + // 处理元组嵌套属性 if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { - tempPropList.Add($"\"{prop.Name}.{element.Name}\""); + // 生成形如:typeof(ValueTuple).GetProperty("Item1") + var tupleTypeName = tupleType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + initializerLines.Add( + $"typeof({tupleTypeName}).GetProperty(\"{element.Name}\") ?? " + + $"throw new InvalidOperationException(\"Tuple element {element.Name} not found\")"); } } - else - { - tempPropList.Add($"\"{prop.Name}\""); - } } - code.Append(string.Join(",", tempPropList)); - + code.AppendLine(string.Join(",\n", initializerLines)); code.AppendLine(" };"); } + + private static void AddPropertyInitializer( + INamedTypeSymbol classSymbol, + IPropertySymbol prop, + List initializerLines) + { + var classType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + initializerLines.Add( + $"typeof({classType}).GetProperty(\"{prop.Name}\", " + + "System.Reflection.BindingFlags.Public | " + + "System.Reflection.BindingFlags.Instance) ?? " + + $"throw new InvalidOperationException(\"Property {prop.Name} not found\")"); + } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs deleted file mode 100644 index e0bedd4..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntityAccessor.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -#nullable enable -using System; -using System.Collections.Generic; -using JiShe.CollectBus.Analyzers.Shared; -namespace JiShe.CollectBus.IoTDB.Model; - -public sealed class TableModelSingleMeasuringEntityAccessor3 : ISourceEntityAccessor> -{ - public static string GetSingleColumn_Item1(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj) => obj.SingleColumn.Item1; - public static void SetSingleColumn_Item1(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj, string value) => obj.SingleColumn = (value, obj.SingleColumn.Item2); - public static T GetSingleColumn_Item2(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj) => obj.SingleColumn.Item2; - public static void SetSingleColumn_Item2(global::JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity obj, T value) => obj.SingleColumn = (obj.SingleColumn.Item1, value); - public static string GetSystemName(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.SystemName; - public static void SetSystemName(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.SystemName = value; - public static string GetProjectId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.ProjectId; - public static void SetProjectId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.ProjectId = value; - public static string GetDeviceType(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.DeviceType; - public static void SetDeviceType(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.DeviceType = value; - public static string GetDeviceId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.DeviceId; - public static void SetDeviceId(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, string value) => obj.DeviceId = value; - public static long GetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj) => obj.Timestamps; - public static void SetTimestamps(JiShe.CollectBus.IoTDB.Model.IoTEntity obj, long value) => obj.Timestamps = value; - public List PropertyNameList { get; } = new List() - { -"SingleColumn.Item1","SingleColumn.Item2","SystemName","ProjectId","DeviceType","DeviceId","Timestamps" }; - public object GetPropertyValue(JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity targetEntity, string propertyName) - { - return propertyName switch - { - "SingleColumn.Item1" => GetSingleColumn_Item1(targetEntity), - "SingleColumn.Item2" => GetSingleColumn_Item2(targetEntity), - "SystemName" => GetSystemName(targetEntity), - "ProjectId" => GetProjectId(targetEntity), - "DeviceType" => GetDeviceType(targetEntity), - "DeviceId" => GetDeviceId(targetEntity), - "Timestamps" => GetTimestamps(targetEntity), - _ => throw new ArgumentException($"Unknown property: {propertyName}") - }; - } - public void SetPropertyValue(JiShe.CollectBus.IoTDB.Model.TableModelSingleMeasuringEntity targetEntity, string propertyName, object value) - { - switch (propertyName) - { - case "SingleColumn.Item1": - SetSingleColumn_Item1( - targetEntity, (string)value); - break; - case "SingleColumn.Item2": - SetSingleColumn_Item2( - targetEntity, (T)value); - break; - case "SystemName": - SetSystemName( - targetEntity, (string)value); - break; - case "ProjectId": - SetProjectId( - targetEntity, (string)value); - break; - case "DeviceType": - SetDeviceType( - targetEntity, (string)value); - break; - case "DeviceId": - SetDeviceId( - targetEntity, (string)value); - break; - case "Timestamps": - SetTimestamps( - targetEntity, (long)value); - break; - default: - throw new ArgumentException($"Unknown property: {propertyName}"); - } - } -} diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs index a469147..73ecd15 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/T37612012ProtocolPlugin.cs @@ -715,10 +715,10 @@ namespace JiShe.CollectBus.Protocol.T37612012 /// public virtual List Generate_DataUnit(DataTimeMark timeMark) { - List values = new List - { - SplitDataTime(timeMark.DataTime)//数据时间 - }; + List values = new List(); + + values.AddRange(SplitDataTime(timeMark.DataTime));//数据时间 + if (timeMark.Density > 0) values.Add(timeMark.Density.HexToDecStr().PadLeft(2, '0'));//密度 if (timeMark.Point > 0) @@ -727,13 +727,13 @@ namespace JiShe.CollectBus.Protocol.T37612012 } - private string SplitDataTime(DateTime dataTime) + private List SplitDataTime(DateTime dataTime) { //2101060815 - List values = new List() { $"{dataTime}:YY", $"{dataTime}:MM", $"{dataTime}:dd", $"{dataTime}:HH", $"{dataTime}:mm", }; - + List values = new List() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", }; values.Reverse(); - return string.Join("", values); + return values; + //return string.Join("", values); } #endregion diff --git a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs index c129194..17ae182 100644 --- a/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs +++ b/services/JiShe.CollectBus.Application/DataChannels/DataChannelManageService.cs @@ -125,13 +125,13 @@ namespace JiShe.CollectBus.DataChannels // 批量写入数据库 await _dbProvider.BatchInsertAsync(metadata, records); - // 限流推送Kafka - await DeviceGroupBalanceControl.ProcessWithThrottleAsync( - items: records, - deviceIdSelector: data => data.DeviceId, - processor: async (data, groupIndex) => - await KafkaProducerIssuedMessageAction(topicName, data, groupIndex) - ); + //// 限流推送Kafka + //await DeviceGroupBalanceControl.ProcessWithThrottleAsync( + // items: records, + // deviceIdSelector: data => data.DeviceId, + // processor: async (data, groupIndex) => + // await KafkaProducerIssuedMessageAction(topicName, data, groupIndex) + //); } catch (Exception ex) { diff --git a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs index e75ad84..47b8a99 100644 --- a/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs +++ b/services/JiShe.CollectBus.Application/ScheduledMeterReading/BasicScheduledMeterReadingService.cs @@ -336,47 +336,47 @@ namespace JiShe.CollectBus.ScheduledMeterReading //此处代码不要删除 #if DEBUG - //var timeDensity = "15"; - //var serverTagName = "JiSheCollectBus2"; - //var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - //var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; - //var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + var timeDensity = "15"; + var serverTagName = "JiSheCollectBus2"; + var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; + var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}"; List meterInfos = new List(); - //List focusAddressDataLista = new List(); - //var timer1 = Stopwatch.StartNew(); + List focusAddressDataLista = new List(); + var timer1 = Stopwatch.StartNew(); - //var allIds = new HashSet(); - //decimal? score = null; - //string member = null; + var allIds = new HashSet(); + decimal? score = null; + string member = null; - //while (true) - //{ - // var page = await _redisDataCacheService.GetAllPagedData( - // redisCacheMeterInfoHashKeyTemp, - // redisCacheMeterInfoZSetScoresIndexKeyTemp, - // pageSize: 1000, - // lastScore: score, - // lastMember: member); + while (true) + { + var page = await _redisDataCacheService.GetAllPagedData( + redisCacheMeterInfoHashKeyTemp, + redisCacheMeterInfoZSetScoresIndexKeyTemp, + pageSize: 1000, + lastScore: score, + lastMember: member); - // meterInfos.AddRange(page.Items); - // focusAddressDataLista.AddRange(page.Items.Select(d => $"{d.MeterId}")); - // foreach (var item in page.Items) - // { - // if (!allIds.Add(item.MemberId)) - // { - // _logger.LogError($"{item.MemberId}Duplicate data found!"); - // } - // } - // if (!page.HasNext) break; - // score = page.NextScore; - // member = page.NextMember; - //} + meterInfos.AddRange(page.Items); + focusAddressDataLista.AddRange(page.Items.Select(d => $"{d.MeterId}")); + foreach (var item in page.Items) + { + if (!allIds.Add(item.MemberId)) + { + _logger.LogError($"{item.MemberId}Duplicate data found!"); + } + } + if (!page.HasNext) break; + score = page.NextScore; + member = page.NextMember; + } - //timer1.Stop(); - //_logger.LogError($"电表初始化读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); - //DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); + timer1.Stop(); + _logger.LogError($"电表初始化读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); + DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); return; #else var meterInfos = await GetAmmeterInfoList(gatherCode);