diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs index 15179af..bad9528 100644 --- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs +++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs @@ -1,4 +1,5 @@ -using Microsoft.CodeAnalysis; +using JiShe.CollectBus.Analyzers.Shared; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; @@ -40,18 +41,37 @@ namespace JiShe.CollectBus.IncrementalGenerator private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context) { var classDecl = (ClassDeclarationSyntax)context.Node; - var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName); + var semanticModel = context.SemanticModel; - foreach (var attribute in classDecl.AttributeLists.SelectMany(al => al.Attributes)) + // 获取类符号 + var classSymbol = semanticModel.GetDeclaredSymbol(classDecl) as INamedTypeSymbol; + if (classSymbol == null) return null; + + // 检查是否包含 SourceAnalyzers 特性 + var sourceAnalyzerAttr = classSymbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == AttributeFullName); + + // 必须包含 EntityType 参数 + if (sourceAnalyzerAttr == null || + sourceAnalyzerAttr.ConstructorArguments.Length == 0) { - var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; - if (symbol is IMethodSymbol ctor && - SymbolEqualityComparer.Default.Equals(ctor.ContainingType, attributeType)) - { - return classDecl; - } + return null; } - return null; + + return classDecl; + + //var classDecl = (ClassDeclarationSyntax)context.Node; + //var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName); + + //foreach (var attribute in classDecl.AttributeLists.SelectMany(al => al.Attributes)) + //{ + // var symbol = context.SemanticModel.GetSymbolInfo(attribute).Symbol; + // if (symbol is IMethodSymbol ctor && + // SymbolEqualityComparer.Default.Equals(ctor.ContainingType, attributeType)) + // { + // return classDecl; + // } + //} + //return null; } /// @@ -154,6 +174,25 @@ namespace JiShe.CollectBus.IncrementalGenerator Compilation compilation, HashSet processedTypes) { + // 获取 SourceAnalyzers 特性的 EntityType 参数 + var sourceAnalyzerAttr = classSymbol.GetAttributes() + .FirstOrDefault(attr => + attr.AttributeClass?.ToDisplayString() == AttributeFullName); + + // 解析 EntityType 枚举值 + string entityTypeValue = "EntityTypeEnum.Other"; // 默认值 + if (sourceAnalyzerAttr != null && + sourceAnalyzerAttr.ConstructorArguments.Length > 0) + { + var arg = sourceAnalyzerAttr.ConstructorArguments[0]; + if (arg.Kind == TypedConstantKind.Enum && + arg.Type is INamedTypeSymbol enumType) + { + int enumValue = (int)arg.Value!; + entityTypeValue = GetEnumMemberName(enumType, enumValue); + } + } + var code = new StringBuilder(); code.AppendLine("// "); code.AppendLine("#nullable enable"); @@ -185,12 +224,14 @@ namespace JiShe.CollectBus.IncrementalGenerator //类名称 code.AppendLine($" public string EntityName {{get;}} = \"{classSymbol.Name}\";"); - + // 添加 EntityType 属性 + code.AppendLine($" public EntityTypeEnum? EntityType {{ get; }} = {entityTypeValue};"); + foreach (var prop in propList) { // 安全类型转换 if (prop.Type is not ITypeSymbol propType) continue; - + if (propType is INamedTypeSymbol namedType) { GenerateStandardAccessors(prop, namedType, code); @@ -262,7 +303,7 @@ namespace JiShe.CollectBus.IncrementalGenerator : $"obj.{propName}.{elements[i].Name}"; } } - + /// /// 处理System.Tuple类型的访问器生成 /// @@ -300,7 +341,7 @@ namespace JiShe.CollectBus.IncrementalGenerator } } } - + /// /// 增强的工厂类实现 /// @@ -381,7 +422,7 @@ namespace JiShe.CollectBus.IncrementalGenerator $"Get{prop.Name}_{element.Name}(targetEntity),"); } } - + } code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")"); @@ -425,7 +466,7 @@ namespace JiShe.CollectBus.IncrementalGenerator code.AppendLine($" targetEntity, ({elementType})value);"); code.AppendLine(" break;"); } - } + } } code.AppendLine(" default:"); @@ -475,10 +516,10 @@ namespace JiShe.CollectBus.IncrementalGenerator /// 生成当前类属性信息集合 /// private static void GenerateEntityMemberInfoList( - IEnumerable propList, - StringBuilder code, - Compilation compilation, - INamedTypeSymbol classSymbol) + IEnumerable propList, + StringBuilder code, + Compilation compilation, + INamedTypeSymbol classSymbol) { code.AppendLine(" public List MemberList { get; } = new()"); code.AppendLine(" {"); @@ -487,8 +528,10 @@ namespace JiShe.CollectBus.IncrementalGenerator foreach (var prop in propList) { - var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var parentType = prop.ContainingType.ToDisplayString(); + var entityType = prop.ContainingType.ToDisplayString();//entity 实体类型名称 + var propType = prop.Type;//实体属性的类型 + var propTypeName = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32") // 处理主属性 var propAttributes = prop.GetAttributes() @@ -503,9 +546,10 @@ namespace JiShe.CollectBus.IncrementalGenerator mainMember.Append( $"new EntityMemberInfo(" + $"\"{prop.Name}\", " + - $"typeof({propType}), " + - $"(e) => Get{prop.Name}(({parentType})e), " + - $"(e, v) => Set{prop.Name}(({parentType})e, ({propType})v))"); + $"typeof({propTypeName}), " + + $"\"{declaredTypeName}\", " + + $"(e) => Get{prop.Name}(({entityType})e), " + + $"(e, v) => Set{prop.Name}(({entityType})e, ({propTypeName})v))"); if (attributeInitializers.Any()) { @@ -516,20 +560,22 @@ namespace JiShe.CollectBus.IncrementalGenerator initializerLines.Add(mainMember.ToString()); - // 处理元组元素(假设不需要处理元组元素的特性) + // 处理元组元素,(暂不需要处理元组元素的特性) if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType) { foreach (var element in tupleType.TupleElements) { - var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var elementName = element.Name; + var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);//元组元素的类型 + var elementName = element.Name;//元组元素名称 + var elementDeclaredName = element.Type.Name;//元组元素类型名称 initializerLines.Add( - $"new EntityMemberInfo(" + - $"\"{prop.Name}.{elementName}\", " + - $"typeof({elementType}), " + - $"(e) => Get{prop.Name}_{elementName}(({parentType})e), " + - $"(e, v) => Set{prop.Name}_{elementName}(({parentType})e, ({elementType})v))"); + $"new EntityMemberInfo(" + + $"\"{prop.Name}.{elementName}\", " + + $"typeof({elementType}), " + + $"\"{elementDeclaredName}\", " + + $"(e) => Get{prop.Name}_{elementName}(({entityType})e), " + + $"(e, v) => Set{prop.Name}_{elementName}(({entityType})e, ({elementType})v))"); } } } @@ -621,5 +667,23 @@ namespace JiShe.CollectBus.IncrementalGenerator { return attribute.AttributeClass?.ToDisplayString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; } + + /// + /// 获取枚举的参数 + /// + /// + /// + /// + private static string GetEnumMemberName(INamedTypeSymbol enumType, int value) + { + foreach (var member in enumType.GetMembers().OfType()) + { + if (member.ConstantValue is int intValue && intValue == value) + { + return $"{enumType.ToDisplayString()}.{member.Name}"; + } + } + return $"{enumType.ToDisplayString()}.Other"; + } } } \ No newline at end of file diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/EntityTypeAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/EntityTypeAttribute.cs deleted file mode 100644 index 89a4e38..0000000 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/EntityTypeAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using JiShe.CollectBus.IoTDB.Enums; - -namespace JiShe.CollectBus.IoTDB.Attributes -{ - /// - /// IoTDB实体类型特性 - /// - [AttributeUsage(AttributeTargets.Class)] - public class EntityTypeAttribute : System.Attribute - { - public EntityTypeEnum EntityType { get; } - - - public EntityTypeAttribute(EntityTypeEnum entityType) - { - EntityType = entityType; - } - } -} diff --git a/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs index ba0ca12..5f986b5 100644 --- a/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs +++ b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs @@ -1,5 +1,4 @@ -using JiShe.CollectBus.IoTDB.Enums; - + namespace JiShe.CollectBus.IoTDB.Attributes { /// diff --git a/modules/JiShe.CollectBus.IoTDB/Model/Class1.cs b/modules/JiShe.CollectBus.IoTDB/Model/Class1.cs new file mode 100644 index 0000000..9bcd5ff --- /dev/null +++ b/modules/JiShe.CollectBus.IoTDB/Model/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.IoTDB.Model +{ + internal class Class1 + { + } +} diff --git a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs index 40403ed..f2d55a5 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs @@ -1,4 +1,5 @@ using JiShe.CollectBus.Common.Attributes; +using JiShe.CollectBus.Common.Consts; using JiShe.CollectBus.IoTDB.Attributes; namespace JiShe.CollectBus.IoTDB.Model @@ -20,6 +21,12 @@ namespace JiShe.CollectBus.IoTDB.Model [TAGColumn] public string ProjectId { get; set; } + /// + /// 数据类型 + /// + [TAGColumn] + public string DataType { get; set; } = IOTDBDataTypeConst.Data; + /// /// 设备类型集中器、电表、水表、流量计、传感器等 /// diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs index a5c98cf..376b677 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs @@ -1,14 +1,12 @@ using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.IoTDB.Attributes; namespace JiShe.CollectBus.IoTDB.Model { /// /// Table模型单项数据实体 - /// - [EntityType(EntityTypeEnum.TableModel)] - [SourceAnalyzers] + /// + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class TableModelSingleMeasuringEntity : IoTEntity { /// diff --git a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs index 6244cdf..56a6c54 100644 --- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs +++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs @@ -1,14 +1,12 @@ using JiShe.CollectBus.Analyzers.Shared; -using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.IoTDB.Attributes; namespace JiShe.CollectBus.IoTDB.Model { /// /// Tree模型单项数据实体 /// - [EntityType(EntityTypeEnum.TreeModel)] - [SourceAnalyzers] + [SourceAnalyzers(EntityTypeEnum.TreeModel)] public class TreeModelSingleMeasuringEntity : IoTEntity { /// diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs b/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs index a093bb7..f48d218 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/DeviceMetadata.cs @@ -1,5 +1,5 @@ using Apache.IoTDB; -using JiShe.CollectBus.IoTDB.Enums; +using JiShe.CollectBus.Analyzers.Shared; namespace JiShe.CollectBus.IoTDB.Provider { @@ -9,9 +9,9 @@ namespace JiShe.CollectBus.IoTDB.Provider public class DeviceMetadata { /// - /// IoTDB实体类型枚举 + /// 实体类型枚举 /// - public EntityTypeEnum EntityType { get; set; } + public EntityTypeEnum? EntityType { get; set; } /// /// 是否有单测量值 diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs b/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs index 6a1a596..57e1b09 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/DevicePathBuilder.cs @@ -15,7 +15,7 @@ namespace JiShe.CollectBus.IoTDB.Provider /// public static string GetDevicePath(T entity) where T : IoTEntity { - return $"root.{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.`{entity.DeviceId}`"; + return $"root.{entity.SystemName.ToLower()}.`{entity.ProjectId}`.`{entity.DeviceType}`.{entity.DataType}.`{entity.DeviceId}`"; } diff --git a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs index c88403f..bacbf61 100644 --- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs +++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs @@ -195,6 +195,8 @@ namespace JiShe.CollectBus.IoTDB.Provider } ); + metadata.EntityType = accessor.EntityType; + return await Task.FromResult(metaData); } @@ -262,26 +264,31 @@ namespace JiShe.CollectBus.IoTDB.Provider var devicePaths = new HashSet(); List tempColumnNames = new List(); tempColumnNames.AddRange(metadata.ColumnNames); - + var accessor = SourceEntityAccessorFactory.GetAccessor(); - var entityTypeAttribute = typeof(T).GetCustomAttribute(); + var memberCache = new Dictionary(); // 缓存优化查询 + // 预构建成员缓存(Key: NameOrPath) + foreach (var member in accessor.MemberList) + { + memberCache[member.NameOrPath] = member; + } - if (entityTypeAttribute == null) + if (accessor.EntityType == null || metadata.EntityType == null) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101"); } - if (metadata.EntityType != entityTypeAttribute.EntityType) + if (metadata.EntityType != accessor.EntityType) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致,属于异常情况,-102"); } - if (metadata.EntityType == Enums.EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true) + if (metadata.EntityType == EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103"); } - else if (metadata.EntityType == Enums.EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false) + else if (metadata.EntityType == EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false) { throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104"); } @@ -299,13 +306,31 @@ namespace JiShe.CollectBus.IoTDB.Provider var rowValues = new List(); foreach (var measurement in tempColumnNames) - { - var value = accessor.GetPropertyValue(entity, measurement); + { + if (!memberCache.TryGetValue(measurement, out var member)) + { + throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName}没有找到{measurement}对应的member信息,-105"); + } + + var value = member.GetValue(entity); + + // 特性查询优化 + var attributes = member.CustomAttributes ?? Enumerable.Empty(); + var singleMeasuringAttr = attributes.OfType().FirstOrDefault(); + if (singleMeasuringAttr != null)//如果是单侧点 + { + var tupleItemKey = $"{member.NameOrPath}.Item2"; + if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember)) + { + throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构时{accessor.EntityName} 没有找到{measurement}对应的member Item2 信息,-106"); + } + + value = tupleMember.GetValue(entity); + } if (value != null) { - Type tupleType = value.GetType(); - var tempValue = tupleType.Name.ToUpper() switch + var tempValue = member.DeclaredTypeName.ToUpper() switch { "DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(), _ => value @@ -319,70 +344,6 @@ 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); - // } - - // } - - //} - values.Add(rowValues); //如果指定了路径 @@ -573,16 +534,20 @@ namespace JiShe.CollectBus.IoTDB.Provider var results = new List(); var metadata = await GetMetadata(); - var properties = typeof(T).GetProperties(); + var accessor = SourceEntityAccessorFactory.GetAccessor(); + var memberCache = new Dictionary(); // 缓存优化查询 + + // 预构建成员缓存(Key: NameOrPath) + foreach (var member in accessor.MemberList) + { + memberCache[member.NameOrPath] = member; + } var columns = new List() { "Timestamps" }; var dataTypes = new List() { TSDataType.TIMESTAMP }; columns.AddRange(metadata.ColumnNames); dataTypes.AddRange(metadata.DataTypes); - //metadata.ColumnNames.Insert(0, "Timestamps"); - //metadata.DataTypes.Insert(0, TSDataType.TIMESTAMP); - var accessor = SourceEntityAccessorFactory.GetAccessor(); while (dataSet.HasNext() && results.Count < pageSize) { @@ -598,23 +563,20 @@ namespace JiShe.CollectBus.IoTDB.Provider var value = record.Values[indexOf]; TSDataType tSDataType = dataTypes[indexOf]; - var prop = properties.FirstOrDefault(p => - p.Name.Equals(measurement, StringComparison.OrdinalIgnoreCase)); - if (prop != null && !(value is System.DBNull)) + if (!memberCache.TryGetValue(measurement, out var member) && !(value is System.DBNull)) { - dynamic tempValue = GetTSDataValue(tSDataType, value); + throw new Exception($"{nameof(ParseResults)} 解析查询结果 {accessor.EntityName} 属性赋值出现异常,没有找到{measurement}对应的 member信息"); + } - if (measurement.ToLower().EndsWith("time")) - { - //typeof(T).GetProperty(measurement)?.SetValue(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); + dynamic tempValue = GetTSDataValue(tSDataType, value); - accessor.SetPropertyValue(entity, measurement, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); - } - else - { - accessor.SetPropertyValue(entity, measurement, tempValue); - //typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue); - } + if (measurement.ToLower().EndsWith("time")) + { + member.Setter(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds)); + } + else + { + member.Setter(entity, tempValue); } } @@ -634,83 +596,58 @@ namespace JiShe.CollectBus.IoTDB.Provider private List CollectColumnMetadata(ISourceEntityAccessor accessor) { var columns = new List(); + var memberCache = new Dictionary(); // 缓存优化查询 + + // 预构建成员缓存(Key: NameOrPath) + foreach (var member in accessor.MemberList) + { + memberCache[member.NameOrPath] = member; + } foreach (var member in accessor.MemberList) { - //元组的子项字段详情不处理。 - if (member.NameOrPath.Contains(".Item")) - { - continue; - } - - string declaredTypeName = string.Empty; + // 过滤元组子项 + if (member.NameOrPath.Contains(".Item")) continue; - Type declaredType = member.DeclaredType;//属性的类型,如string,int等 + // 类型名称处理 + Type declaredType = member.DeclaredType; + var underlyingType = Nullable.GetUnderlyingType(declaredType); + string declaredTypeName = underlyingType?.Name ?? member.DeclaredTypeName; - // 处理可空类型 - if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>)) + // 特性查询优化 + var attributes = member.CustomAttributes ?? Enumerable.Empty(); + var tagAttr = attributes.OfType().FirstOrDefault(); + var attrColumn = attributes.OfType().FirstOrDefault(); + var fieldColumn = attributes.OfType().FirstOrDefault(); + var singleMeasuringAttr = attributes.OfType().FirstOrDefault(); + + // 构建ColumnInfo + ColumnInfo? column = null; + if (tagAttr != null) { - Type underlyingType = Nullable.GetUnderlyingType(declaredType); - declaredTypeName = underlyingType.Name; + column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(declaredTypeName), false); } - else + else if (attrColumn != null) { - declaredTypeName = member.NameOrPath; + column = new ColumnInfo(member.NameOrPath, ColumnCategory.ATTRIBUTE, GetDataTypeFromTypeName(declaredTypeName), false); + } + else if (fieldColumn != null) + { + column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(declaredTypeName), false); } - - var tagAttr = member.CustomAttributes?.OfType().FirstOrDefault(); - var attrColumn = member.CustomAttributes?.OfType().FirstOrDefault(); - var fieldColumn = member.CustomAttributes?.OfType().FirstOrDefault(); - - //判断是否是单测数据 - var singleMeasuringAttribute = member.CustomAttributes?.OfType().FirstOrDefault(); - - //先获取Tag标签和属性标签 - ColumnInfo? column = tagAttr != null ? new ColumnInfo( - name: member.NameOrPath, - category: ColumnCategory.TAG, - dataType: GetDataTypeFromTypeName(declaredTypeName), - false - ) : attrColumn != null ? new ColumnInfo( - member.NameOrPath, - ColumnCategory.ATTRIBUTE, - GetDataTypeFromTypeName(declaredTypeName), - false - ) : fieldColumn != null ? new ColumnInfo( - member.NameOrPath, - ColumnCategory.FIELD, - GetDataTypeFromTypeName(declaredTypeName), - false) - : null; - - //检查是不是单侧点模式 - if (singleMeasuringAttribute != null && column == null) + // 单测模式处理 + if (singleMeasuringAttr != null && column == null) { - //warning: 单侧点模式注意事项 - //Entity实体 字段类型是 Tuple,Item1=>测点名称,Item2=>测点值,泛型 - //只有一个Filed字段。 - //MeasuringName 默认为 SingleMeasuringAttribute.FieldName,以便于在获取对应的Value的时候重置为 Item1 的值。 - - Type tupleType = accessor.MemberList.Where(d => d.NameOrPath == $"{member.NameOrPath}.Item2").FirstOrDefault()?.DeclaredType; - - if (tupleType == null) + var tupleItemKey = $"{member.NameOrPath}.Item2"; + if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember)) { - throw new Exception($"{nameof(CollectColumnMetadata)} {accessor.EntityName} {member.NameOrPath} 属性解析异常"); + throw new Exception($"{nameof(CollectColumnMetadata)} {accessor.EntityName} {member.NameOrPath} 单侧点属性解析异常"); } - - column = new ColumnInfo( - member.NameOrPath, - ColumnCategory.FIELD, - GetDataTypeFromTypeName(tupleType.Name), - true - ); + column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(tupleMember.DeclaredTypeName), true); } - if (column.HasValue) - { - columns.Add(column.Value); - } + if (column.HasValue) columns.Add(column.Value); } return columns; } @@ -740,15 +677,6 @@ namespace JiShe.CollectBus.IoTDB.Provider ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE, metadata); ProcessCategory(groupedColumns, ColumnCategory.FIELD, metadata); - var entityTypeAttribute = typeof(T).GetCustomAttribute(); - - if (entityTypeAttribute == null) - { - throw new ArgumentException($"{nameof(BuildDeviceMetadata)} 构建设备元数据时 {nameof(IoTEntity)} 的EntityType 没有指定,属于异常情况,-101"); - } - - metadata.EntityType = entityTypeAttribute.EntityType; - return metadata; } diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs index b8dbcb4..9162ab0 100644 --- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs +++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/DataStorage.cs @@ -93,8 +93,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{data.DeviceId}", - DeviceType = $"{data.DeviceType.ToString()}.{IOTDBDataType.Data}", + DeviceType = $"{data.DeviceType.ToString()}", ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Data, Timestamps = data.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), SingleMeasuring = (data.FiledName ?? string.Empty, data.DataValue ?? default) }; @@ -196,8 +197,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{item.DeviceId}", - DeviceType = $"{item.DeviceType}.{IOTDBDataType.Data}", + DeviceType = $"{item.DeviceType}", ProjectId = $"{item.ProjectId}", + DataType = IOTDBDataTypeConst.Data, Timestamps = item.TimeSpan!.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity).GetDateTimeOffset().ToUnixTimeNanoseconds(), // TODO:这里暂时格式化15分钟数据,需要进行调整 SingleMeasuring =(item.FiledName ?? string.Empty, item.DataValue ?? default) }; @@ -221,7 +223,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData SystemName = _applicationOptions.SystemType, ProjectId = $"{item.ProjectId}", DeviceType = $"{item.DeviceType}", - DeviceId = $"{item.DeviceId}", + DeviceId = $"{item.DeviceId}", Timestamps = DateTime.Now.CheckTimePoint().GetDateTimeOffset().ToUnixTimeNanoseconds(), DatabaseBusiID = item.DatabaseBusiID, PendingCopyReadTime = item.TimeSpan.Value.GetFormatTime(analysisBaseDto.DensityUnit, analysisBaseDto.TimeDensity), @@ -280,8 +282,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{data.DeviceId}", - DeviceType = $"{data.DeviceType}.{IOTDBDataType.Status}", + DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Data, Timestamps = timestamps, SingleMeasuring = (data.FiledName!, data.DataValue!) }; @@ -292,8 +295,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{data.DeviceId}", - DeviceType = $"{data.DeviceType}.{IOTDBDataType.Status}", + DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Data, Timestamps = timestamps, SingleMeasuring = (ConcentratorStatusFieldConst.FrameData, analysisBaseDto.HexMessage ?? string.Empty) }; @@ -306,9 +310,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{data.DeviceId}", - DeviceType = $"{data.DeviceType}.{IOTDBDataType.Status}", + DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", Timestamps = timestamps, + DataType = IOTDBDataTypeConst.Status, SingleMeasuring = (ConcentratorStatusFieldConst.RecordingTime, (data.TimeSpan.HasValue ? data.TimeSpan.Value : DateTime.Now).GetDateTimeOffset().ToUnixTimeNanoseconds()) }; _runtimeContext.UseTableSessionPool = false; // 使树模型池 @@ -318,8 +323,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData { SystemName = _applicationOptions.SystemType, DeviceId = $"{data.DeviceId}", - DeviceType = $"{data.DeviceType}.{IOTDBDataType.Status}", + DeviceType = $"{data.DeviceType}", ProjectId = $"{data.ProjectId}", + DataType = IOTDBDataTypeConst.Status, Timestamps = timestamps, SingleMeasuring = (ConcentratorStatusFieldConst.Remark, data.FiledDesc ?? string.Empty) }; diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs index ca1d0db..1e1e6cb 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeter.cs @@ -1,12 +1,10 @@ using JiShe.CollectBus.Analyzers.Shared; using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Enums; using JiShe.CollectBus.IoTDB.Model; namespace JiShe.CollectBus.Ammeters { - [EntityType(EntityTypeEnum.TableModel)] - [SourceAnalyzers] + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class ElectricityMeter : IoTEntity { [ATTRIBUTEColumn] diff --git a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs index 5fb6010..49b5abe 100644 --- a/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs +++ b/services/JiShe.CollectBus.Domain/Ammeters/ElectricityMeterTreeModel.cs @@ -1,13 +1,11 @@ using JiShe.CollectBus.Analyzers.Shared; using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Enums; using JiShe.CollectBus.IoTDB.Model; using System; namespace JiShe.CollectBus.Ammeters { - [EntityType(EntityTypeEnum.TreeModel)] - [SourceAnalyzers] + [SourceAnalyzers(EntityTypeEnum.TreeModel)] 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 1d361be..c812f56 100644 --- a/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs +++ b/services/JiShe.CollectBus.Domain/IotSystems/MeterReadingRecords/MeterReadingTelemetryPacketInfo.cs @@ -1,6 +1,5 @@ using JiShe.CollectBus.Analyzers.Shared; using JiShe.CollectBus.IoTDB.Attributes; -using JiShe.CollectBus.IoTDB.Enums; using JiShe.CollectBus.IoTDB.Model; using System; @@ -9,8 +8,7 @@ namespace JiShe.CollectBus.IotSystems.MeterReadingRecords /// /// 抄读任务数据 /// - [EntityType(EntityTypeEnum.TableModel)] - [SourceAnalyzers] + [SourceAnalyzers(EntityTypeEnum.TableModel)] public class MeterReadingTelemetryPacketInfo : IoTEntity { /// diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs index 28520be..523a5df 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/EntityMemberInfo.cs @@ -19,6 +19,11 @@ namespace JiShe.CollectBus.Analyzers.Shared /// public Type DeclaredType { get; set; } + /// + /// 声明的类型的名称 + /// + public string DeclaredTypeName { get; } + /// /// 获取值 /// @@ -38,11 +43,13 @@ namespace JiShe.CollectBus.Analyzers.Shared public EntityMemberInfo( string nameOrPath, Type declaredType, + string declaredTypeName, Func getter, Action setter) { NameOrPath = nameOrPath; this.DeclaredType = declaredType; + DeclaredTypeName = declaredTypeName; Getter = getter; Setter = setter; } diff --git a/modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs b/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs similarity index 57% rename from modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs rename to shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs index 26c6645..bddaa86 100644 --- a/modules/JiShe.CollectBus.IoTDB/EnumInfo/EntityTypeEnum.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/EntityTypeEnum.cs @@ -1,24 +1,27 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; -namespace JiShe.CollectBus.IoTDB.Enums +namespace JiShe.CollectBus.Analyzers.Shared { /// - /// IoTDB实体类型枚举 + /// 实体类型枚举 /// public enum EntityTypeEnum { /// - /// 树模型 + /// IoTDB树模型 /// TreeModel = 1, /// - /// 表模型 + /// IoTDB表模型 /// TableModel = 2, + + /// + /// 其他情况 + /// + Other = 3 } } diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs index a6256ab..2c3a5b0 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/ISourceEntityAccessor.cs @@ -12,6 +12,11 @@ namespace JiShe.CollectBus.Analyzers.Shared /// string EntityName { get; } + /// + /// 实体类型 + /// + EntityTypeEnum? EntityType { get;} + /// /// 获取属性值 /// diff --git a/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs b/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs index 0b33a6a..ad02607 100644 --- a/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs +++ b/shared/JiShe.CollectBus.Analyzers.Shared/SourceAnalyzersAttribute.cs @@ -8,5 +8,12 @@ namespace JiShe.CollectBus.Analyzers.Shared [AttributeUsage(AttributeTargets.Class)] public class SourceAnalyzersAttribute : Attribute { + public EntityTypeEnum EntityType { get; } + + + public SourceAnalyzersAttribute(EntityTypeEnum entityType) + { + EntityType = entityType; + } } } diff --git a/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs b/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs new file mode 100644 index 0000000..7c076c9 --- /dev/null +++ b/shared/JiShe.CollectBus.Common/Consts/IOTDBDataTypeConst.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Consts +{ + /// + /// IOTDB数据树类型 + /// + public class IOTDBDataTypeConst + { + /// + /// 数据 + /// + public const string Data = "Data"; + + /// + /// 事件 + /// + public const string Event = "Event"; + + /// + /// 状态 + /// + public const string Status = "Status"; + } +} diff --git a/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs b/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs index 5123fab..1d93ff8 100644 --- a/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs +++ b/shared/JiShe.CollectBus.Common/Consts/T37612012PacketItemCodeConst.cs @@ -151,27 +151,7 @@ namespace JiShe.CollectBus.Common.Consts public const string Ic = "0C_49_Ic"; // 当前电压、电流相位角 } - - /// - /// IOTDB数据树类型 - /// - public class IOTDBDataType - { - /// - /// 数据 - /// - public const string Data = "Data"; - - /// - /// 事件 - /// - public const string Event = "Event"; - - /// - /// 状态 - /// - public const string Status = "Status"; - } + /// /// 集中器状态字段