diff --git a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs
index 20951e5..bad9528 100644
--- a/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs
+++ b/modules/JiShe.CollectBus.Analyzers/ComplexTypeSourceAnalyzers.cs
@@ -1,6 +1,9 @@
-using Microsoft.CodeAnalysis;
+using JiShe.CollectBus.Analyzers.Shared;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
@@ -8,7 +11,7 @@ using System.Text;
namespace JiShe.CollectBus.IncrementalGenerator
{
///
- /// 复杂类型源生成器
+ /// 复杂类型增量源生成器
///
[Generator(LanguageNames.CSharp)]
public class ComplexTypeSourceAnalyzers : IIncrementalGenerator
@@ -19,12 +22,7 @@ namespace JiShe.CollectBus.IncrementalGenerator
{
//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),
@@ -39,23 +37,41 @@ namespace JiShe.CollectBus.IncrementalGenerator
}
private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0;
-
private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
- var attributeType = context.SemanticModel.Compilation.GetTypeByMetadataName(AttributeFullName);
+ 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;
}
///
@@ -76,18 +92,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,77 +121,25 @@ 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("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}"); // 调试输出
-
- context.AddSource($"{classSymbol.Name}Extension.g.cs", code);
- }
- }
-
- 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 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);
+ var code3 = BuildAccessorsForSourceEntity(classSymbol, compilation, processedTypes);
+ context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
}
- code.AppendLine("}");
- return code.ToString();
+ // 生成工厂注册代码
+ context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode());
}
- //private static string GetGenericParams(INamedTypeSymbol symbol)
- // => symbol.IsGenericType ? $"<{string.Join(", ", symbol.TypeParameters.Select(t => t.Name))}>" : "";
+ ///
+ /// 获取泛型参数
+ ///
+ ///
+ ///
public static string GetGenericParams(INamedTypeSymbol symbol)
{
if (!symbol.IsGenericType) return "";
@@ -177,51 +147,13 @@ namespace JiShe.CollectBus.IncrementalGenerator
return $"<{string.Join(", ", parameters)}>";
}
- private static void GeneratePropertyAccessors(
- IPropertySymbol prop,
- StringBuilder code,
- Compilation compilation,
- HashSet processedTypes)
- {
- // 关键修复点1:安全类型转换
- if (prop.Type is not ITypeSymbol propType) return;
-
- code.AppendLine($" // Processing property: {prop.Name}");
-
- // 处理元组类型
- if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
- {
- GenerateTupleAccessors(prop, tupleType, code);
- }
- else if (propType is INamedTypeSymbol namedType)
- {
- GenerateStandardAccessors(prop, namedType, code);
- ProcessNestedType(namedType, compilation, processedTypes);
- }
- }
-
- private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code)
- {
- var elements = tupleType.TupleElements;
- var parentType = prop.ContainingType.ToDisplayString();
-
- for (int i = 0; i < elements.Length; i++)
- {
- var element = elements[i];
- if (element.Type is not ITypeSymbol elementType) continue;
-
- var elementName = element.CorrespondingTupleField?.Name ?? $"Item{i + 1}";
- code.AppendLine($" public static {elementType.ToDisplayString()} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
-
- if (prop.SetMethod != null)
- {
- var assignments = elements.Select((e, idx) =>
- idx == i ? "value" : $"obj.{prop.Name}.{e.Name}");
- code.AppendLine($" public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType.ToDisplayString()} value) => obj.{prop.Name} = ({string.Join(", ", assignments)});");
- }
- }
- }
+ ///
+ /// 生成标准属性的访问器
+ ///
+ ///
+ ///
+ ///
private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
{
var parentType = prop.ContainingType.ToDisplayString();
@@ -233,22 +165,525 @@ namespace JiShe.CollectBus.IncrementalGenerator
}
}
- 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 string BuildAccessorsForSourceEntity(
+ INamedTypeSymbol classSymbol,
+ Compilation compilation,
+ HashSet processedTypes)
+ {
+ // 获取 SourceAnalyzers 特性的 EntityType 参数
+ var sourceAnalyzerAttr = classSymbol.GetAttributes()
+ .FirstOrDefault(attr =>
+ attr.AttributeClass?.ToDisplayString() == AttributeFullName);
+
+ // 解析 EntityType 枚举值
+ string entityTypeValue = "EntityTypeEnum.Other"; // 默认值
+ if (sourceAnalyzerAttr != null &&
+ sourceAnalyzerAttr.ConstructorArguments.Length > 0)
+ {
+ var arg = sourceAnalyzerAttr.ConstructorArguments[0];
+ if (arg.Kind == TypedConstantKind.Enum &&
+ arg.Type is INamedTypeSymbol enumType)
+ {
+ int enumValue = (int)arg.Value!;
+ entityTypeValue = GetEnumMemberName(enumType, enumValue);
+ }
+ }
+
+ var code = new StringBuilder();
+ code.AppendLine("// ");
+ code.AppendLine("#nullable enable");
+ code.AppendLine("using System;");
+ code.AppendLine("using System.Reflection;");
+ code.AppendLine("using System.Collections.Generic;");
+ code.AppendLine("using JiShe.CollectBus.Analyzers.Shared;");
+ code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
+ code.AppendLine();
+
+ // 处理泛型类型名称
+ var accessibility = classSymbol.DeclaredAccessibility switch
+ {
+ Accessibility.Public => "public",
+ _ => "internal"
+ };
+
+ var genericParams = classSymbol.IsGenericType
+ ? $"<{string.Join(", ", classSymbol.TypeParameters.Select(t => t.Name))}>"
+ : "";
+
+ code.AppendLine(
+ $"{accessibility} sealed class {classSymbol.Name}Accessor{genericParams} " + // 保留泛型参数
+ $": ISourceEntityAccessor<{classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>");
+
+ code.AppendLine("{");
+
+ var propList = GetAllPropertiesInHierarchy(classSymbol);
+
+ //类名称
+ code.AppendLine($" public string EntityName {{get;}} = \"{classSymbol.Name}\";");
+ // 添加 EntityType 属性
+ code.AppendLine($" public EntityTypeEnum? EntityType {{ get; }} = {entityTypeValue};");
+
+ foreach (var prop in propList)
+ {
+ // 安全类型转换
+ if (prop.Type is not ITypeSymbol propType) continue;
+
+ if (propType is INamedTypeSymbol namedType)
+ {
+ GenerateStandardAccessors(prop, namedType, code);
+ }
+
+ if (propType is INamedTypeSymbol { IsTupleType: true } tupleType)
+ {
+ GenerateTupleAccessors(prop, tupleType, code);
+ }
+ }
+
+ //生成当前类属性名称集合
+ GeneratePropertyListForSourceEntity(propList, code, compilation, classSymbol);
+
+ //生成当前类属性信息集合
+ GenerateEntityMemberInfoList(propList, code, compilation, classSymbol);
+
+
+ //生成当前类属性访问
+ GetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
+
+ //生成当前类属性设置
+ SetGeneratePropertyValueForSourceEntity(propList, code, compilation, classSymbol);
+
+ code.AppendLine("}");
+ return code.ToString();
}
- private static bool ShouldProcessNestedType(INamedTypeSymbol symbol)
+ ///
+ /// 生成ValueTuple元组属性访问器
+ ///
+ ///
+ ///
+ ///
+ private static void GenerateTupleAccessors(
+ IPropertySymbol prop,
+ INamedTypeSymbol tupleType,
+ StringBuilder code)
{
- return symbol.DeclaredAccessibility == Accessibility.Public &&
- !symbol.IsTupleType &&
- !symbol.IsAnonymousType &&
- !symbol.IsImplicitlyDeclared &&
- !symbol.Name.StartsWith("<");
+ var parentType = prop.ContainingType.ToDisplayString();
+ var tupleElements = tupleType.TupleElements;
+
+ for (int i = 0; i < tupleElements.Length; i++)
+ {
+ var element = tupleElements[i];
+ var elementType = element.Type.ToDisplayString();
+ var elementName = element.Name;
+
+ // Getter
+ code.AppendLine($"public static {elementType} Get{prop.Name}_{elementName}({parentType} obj) => obj.{prop.Name}.{elementName};");
+
+ // Setter
+ if (prop.SetMethod != null)
+ {
+ code.AppendLine($"public static void Set{prop.Name}_{elementName}({parentType} obj, {elementType} value) => obj.{prop.Name} = ({string.Join(", ", GetTupleElements(prop.Name, tupleElements, i))});");
+ }
+ }
+ }
+
+ private static IEnumerable GetTupleElements(
+ string propName,
+ ImmutableArray elements,
+ int targetIndex)
+ {
+ for (int i = 0; i < elements.Length; i++)
+ {
+ yield return i == targetIndex
+ ? "value"
+ : $"obj.{propName}.{elements[i].Name}";
+ }
+ }
+
+ ///
+ /// 处理System.Tuple类型的访问器生成
+ ///
+ private static void GenerateSystemTupleAccessors(
+ IPropertySymbol prop,
+ INamedTypeSymbol tupleType,
+ StringBuilder code,
+ INamedTypeSymbol classSymbol)
+ {
+ var parentType = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var elementTypes = tupleType.TypeArguments;
+ var tupleTypeName = tupleType.ToDisplayString();
+
+ for (int i = 0; i < elementTypes.Length; i++)
+ {
+ var elementType = elementTypes[i].ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var elementName = $"Item{i + 1}";
+
+ // Getter
+ code.AppendLine(
+ $" public static {elementType} Get{prop.Name}_{elementName}" +
+ $"({parentType} obj) => obj.{prop.Name}.{elementName};");
+
+ // Setter
+ if (prop.SetMethod != null)
+ {
+ var assignments = elementTypes.Select((_, idx) =>
+ idx == i ? "value" : $"obj.{prop.Name}.Item{idx + 1}"
+ ).ToList();
+
+ code.AppendLine(
+ $" public static void Set{prop.Name}_{elementName}" +
+ $"({parentType} obj, {elementType} value) => " +
+ $"obj.{prop.Name} = new {tupleTypeName}({string.Join(", ", assignments)});");
+ }
+ }
+ }
+
+ ///
+ /// 增强的工厂类实现
+ ///
+ private static string BuildFactoryCode()
+ {
+ return """
+ using System;
+ using System.Collections.Concurrent;
+ using System.Reflection;
+
+ namespace JiShe.CollectBus.Analyzers.Shared;
+
+ public static class SourceEntityAccessorFactory
+ {
+ private static readonly ConcurrentDictionary _accessors = new();
+
+ public static ISourceEntityAccessor GetAccessor()
+ {
+ return (ISourceEntityAccessor)_accessors.GetOrAdd(typeof(T), t =>
+ {
+ // 获取泛型类型定义信息(如果是泛型类型)
+ var isGeneric = t.IsGenericType;
+ var genericTypeDef = isGeneric ? t.GetGenericTypeDefinition() : null;
+ var arity = isGeneric ? genericTypeDef!.GetGenericArguments().Length : 0;
+
+ // 构建访问器类名
+ var typeName = isGeneric
+ ? $"{t.Namespace}.{genericTypeDef!.Name.Split('`')[0]}Accessor`{arity}"
+ : $"{t.Namespace}.{t.Name}Accessor";
+
+ // 尝试从当前程序集加载
+ var accessorType = Assembly.GetAssembly(t)!.GetType(typeName)
+ ?? throw new InvalidOperationException($"Accessor type {typeName} not found");
+
+ // 处理泛型参数
+ if (isGeneric && accessorType.IsGenericTypeDefinition)
+ {
+ accessorType = accessorType.MakeGenericType(t.GetGenericArguments());
+ }
+
+ return Activator.CreateInstance(accessorType)!;
+ });
+ }
+ }
+ """;
+ }
+
+ ///
+ /// 属性访问生成逻辑
+ ///
+ /// 属性集合
+ ///
+ ///
+ ///
+ private static void GetGeneratePropertyValueForSourceEntity(
+ IEnumerable propList,
+ StringBuilder code,
+ Compilation compilation,
+ INamedTypeSymbol classSymbol)
+ {
+ code.AppendLine($" public object GetPropertyValue({classSymbol} targetEntity, string propertyName)");
+ code.AppendLine(" {");
+ code.AppendLine(" return propertyName switch");
+ code.AppendLine(" {");
+
+ foreach (var prop in propList)
+ {
+ code.AppendLine(
+ $" \"{prop.Name}\" => " +
+ $"Get{prop.Name}(targetEntity),");
+
+ if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
+ {
+ foreach (var element in tupleType.TupleElements)
+ {
+ code.AppendLine(
+ $" \"{prop.Name}.{element.Name}\" => " +
+ $"Get{prop.Name}_{element.Name}(targetEntity),");
+ }
+ }
+
+ }
+
+ code.AppendLine(" _ => throw new ArgumentException($\"Unknown property: {propertyName}\")");
+ code.AppendLine(" };");
+ code.AppendLine(" }");
+ }
+
+ ///
+ /// 属性设置生成逻辑
+ ///
+ /// 属性集合
+ ///
+ ///
+ ///
+ private static void SetGeneratePropertyValueForSourceEntity(
+ IEnumerable propList,
+ StringBuilder code,
+ Compilation compilation,
+ INamedTypeSymbol classSymbol)
+ {
+ code.AppendLine($" public void SetPropertyValue({classSymbol} targetEntity, string propertyName, object value)");
+ code.AppendLine(" {");
+ code.AppendLine(" switch (propertyName)");
+ code.AppendLine(" {");
+
+ foreach (var prop in propList)
+ {
+ var propType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ code.AppendLine($" case \"{prop.Name}\":");
+ code.AppendLine($" Set{prop.Name}(");
+ code.AppendLine($" targetEntity, ({propType})value);");
+ code.AppendLine(" break;");
+
+ if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
+ {
+ foreach (var element in tupleType.TupleElements)
+ {
+ var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ code.AppendLine($" case \"{prop.Name}.{element.Name}\":");
+ code.AppendLine($" Set{prop.Name}_{element.Name}(");
+ code.AppendLine($" targetEntity, ({elementType})value);");
+ code.AppendLine(" break;");
+ }
+ }
+ }
+
+ code.AppendLine(" default:");
+ code.AppendLine(" throw new ArgumentException($\"Unknown property: {propertyName}\");");
+ code.AppendLine(" }");
+ code.AppendLine(" }");
+ }
+
+ ///
+ /// 属性名称集合
+ ///
+ /// 属性集合
+ ///
+ ///
+ ///
+ private static void GeneratePropertyListForSourceEntity(
+ IEnumerable propList,
+ StringBuilder code,
+ Compilation compilation,
+ INamedTypeSymbol classSymbol)
+ {
+ code.AppendLine(" public List PropertyNameList {get;} = new List()");
+ code.AppendLine(" {");
+ List tempPropList = new List();
+ foreach (var prop in propList)
+ {
+ if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
+ {
+ foreach (var element in tupleType.TupleElements)
+ {
+ tempPropList.Add($"\"{prop.Name}.{element.Name}\"");
+ }
+ }
+ else
+ {
+ tempPropList.Add($"\"{prop.Name}\"");
+ }
+ }
+
+ code.Append(string.Join(",", tempPropList));
+
+ code.AppendLine(" };");
+ }
+
+
+ ///
+ /// 生成当前类属性信息集合
+ ///
+ private static void GenerateEntityMemberInfoList(
+ IEnumerable propList,
+ StringBuilder code,
+ Compilation compilation,
+ INamedTypeSymbol classSymbol)
+ {
+ code.AppendLine(" public List MemberList { get; } = new()");
+ code.AppendLine(" {");
+
+ var initializerLines = new List();
+
+ foreach (var prop in propList)
+ {
+ var entityType = prop.ContainingType.ToDisplayString();//entity 实体类型名称
+ var propType = prop.Type;//实体属性的类型
+ var propTypeName = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var declaredTypeName = propType.Name; // 直接获取类型名称(如 "Int32")
+
+ // 处理主属性
+ var propAttributes = prop.GetAttributes()
+ .Where(a => !IsCompilerGeneratedAttribute(a))
+ .ToList();
+
+ var attributeInitializers = propAttributes
+ .Select(GenerateAttributeInitializer)
+ .Where(s => !string.IsNullOrEmpty(s));
+
+ var mainMember = new StringBuilder();
+ mainMember.Append(
+ $"new EntityMemberInfo(" +
+ $"\"{prop.Name}\", " +
+ $"typeof({propTypeName}), " +
+ $"\"{declaredTypeName}\", " +
+ $"(e) => Get{prop.Name}(({entityType})e), " +
+ $"(e, v) => Set{prop.Name}(({entityType})e, ({propTypeName})v))");
+
+ if (attributeInitializers.Any())
+ {
+ mainMember.AppendLine();
+ mainMember.Append(" { CustomAttributes = new List");
+ mainMember.Append($" {{ {string.Join(", ", attributeInitializers)} }} }}");
+ }
+
+ initializerLines.Add(mainMember.ToString());
+
+ // 处理元组元素,(暂不需要处理元组元素的特性)
+ if (prop.Type is INamedTypeSymbol { IsTupleType: true } tupleType)
+ {
+ foreach (var element in tupleType.TupleElements)
+ {
+ var elementType = element.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);//元组元素的类型
+ var elementName = element.Name;//元组元素名称
+ var elementDeclaredName = element.Type.Name;//元组元素类型名称
+
+ initializerLines.Add(
+ $"new EntityMemberInfo(" +
+ $"\"{prop.Name}.{elementName}\", " +
+ $"typeof({elementType}), " +
+ $"\"{elementDeclaredName}\", " +
+ $"(e) => Get{prop.Name}_{elementName}(({entityType})e), " +
+ $"(e, v) => Set{prop.Name}_{elementName}(({entityType})e, ({elementType})v))");
+ }
+ }
+ }
+
+ code.AppendLine(string.Join(",\n", initializerLines));
+ code.AppendLine(" };");
+ }
+
+
+ private static string GenerateAttributeInitializer(AttributeData attribute)
+ {
+ if (attribute.AttributeClass == null)
+ return string.Empty;
+
+ var attributeClass = attribute.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ var args = attribute.ConstructorArguments;
+ var namedArgs = attribute.NamedArguments;
+
+ var parameters = new List();
+ foreach (var arg in args)
+ {
+ parameters.Add(ConvertTypedConstantToCode(arg));
+ }
+
+ var constructorArgs = string.Join(", ", parameters);
+
+ var initializer = new StringBuilder();
+ initializer.Append($"new {attributeClass}({constructorArgs})");
+
+ if (namedArgs.Any())
+ {
+ initializer.Append(" { ");
+ var namedArgsList = namedArgs.Select(n => $"{n.Key} = {ConvertTypedConstantToCode(n.Value)}");
+ initializer.Append(string.Join(", ", namedArgsList));
+ initializer.Append(" }");
+ }
+
+ return initializer.ToString();
+ }
+
+ private static string ConvertTypedConstantToCode(TypedConstant constant)
+ {
+ if (constant.IsNull)
+ return "null";
+
+ switch (constant.Kind)
+ {
+ case TypedConstantKind.Array:
+ var elements = constant.Values.Select(ConvertTypedConstantToCode);
+ return $"new[] {{ {string.Join(", ", elements)} }}";
+ case TypedConstantKind.Type:
+ var typeSymbol = (ITypeSymbol)constant.Value!;
+ return $"typeof({typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)})";
+ case TypedConstantKind.Enum:
+ return ConvertEnumTypedConstant(constant);
+ default:
+ return ConvertPrimitiveConstant(constant);
+ }
+ }
+
+ private static string ConvertEnumTypedConstant(TypedConstant constant)
+ {
+ var enumType = constant.Type!;
+ var enumValue = constant.Value!;
+ var enumTypeName = enumType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+
+ foreach (var member in enumType.GetMembers().OfType())
+ {
+ if (member.ConstantValue != null && member.ConstantValue.Equals(enumValue))
+ return $"{enumTypeName}.{member.Name}";
+ }
+
+ return $"({enumTypeName})({enumValue})";
+ }
+
+ private static string ConvertPrimitiveConstant(TypedConstant constant)
+ {
+ var value = constant.Value!;
+ return value switch
+ {
+ string s => $"\"{s}\"",
+ char c => $"'{c}'",
+ bool b => b ? "true" : "false",
+ _ => value.ToString()
+ };
+ }
+
+ private static bool IsCompilerGeneratedAttribute(AttributeData attribute)
+ {
+ return attribute.AttributeClass?.ToDisplayString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute";
+ }
+
+ ///
+ /// 获取枚举的参数
+ ///
+ ///
+ ///
+ ///
+ private static string GetEnumMemberName(INamedTypeSymbol enumType, int value)
+ {
+ foreach (var member in enumType.GetMembers().OfType())
+ {
+ if (member.ConstantValue is int intValue && intValue == value)
+ {
+ return $"{enumType.ToDisplayString()}.{member.Name}";
+ }
+ }
+ return $"{enumType.ToDisplayString()}.Other";
}
}
}
\ No newline at end of file
diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs
deleted file mode 100644
index 3610c00..0000000
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/EntityTypeAttribute.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using JiShe.CollectBus.IoTDB.Enums;
-
-namespace JiShe.CollectBus.IoTDB.Attribute
-{
- ///
- /// 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/Attribute/ATTRIBUTEColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs
similarity index 83%
rename from modules/JiShe.CollectBus.IoTDB/Attribute/ATTRIBUTEColumnAttribute.cs
rename to modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs
index d188c36..7ef13f3 100644
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/ATTRIBUTEColumnAttribute.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Attributes/ATTRIBUTEColumnAttribute.cs
@@ -1,4 +1,4 @@
-namespace JiShe.CollectBus.IoTDB.Attribute
+namespace JiShe.CollectBus.IoTDB.Attributes
{
///
/// Column分类标记特性(ATTRIBUTE字段),也就是属性字段
diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs
similarity index 82%
rename from modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs
rename to modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs
index 7cabdf4..43d699f 100644
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/FIELDColumnAttribute.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Attributes/FIELDColumnAttribute.cs
@@ -1,4 +1,4 @@
-namespace JiShe.CollectBus.IoTDB.Attribute
+namespace JiShe.CollectBus.IoTDB.Attributes
{
///
/// Column分类标记特性(FIELD字段),数据列字段
diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs
similarity index 91%
rename from modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs
rename to modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs
index 5f0ca07..481bfa2 100644
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/SingleMeasuringAttribute.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Attributes/SingleMeasuringAttribute.cs
@@ -1,4 +1,4 @@
-namespace JiShe.CollectBus.IoTDB.Attribute
+namespace JiShe.CollectBus.IoTDB.Attributes
{
///
/// 用于标识当前实体为单侧点模式,单侧点模式只有一个Filed标识字段,类型是Tuple,Item1=>测点名称,Item2=>测点值,泛型
diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs
similarity index 82%
rename from modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs
rename to modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs
index 6f40a47..48a3830 100644
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/TAGColumnAttribute.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Attributes/TAGColumnAttribute.cs
@@ -1,4 +1,4 @@
-namespace JiShe.CollectBus.IoTDB.Attribute
+namespace JiShe.CollectBus.IoTDB.Attributes
{
///
/// Column分类标记特性(TAG字段),标签字段
diff --git a/modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs
similarity index 85%
rename from modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs
rename to modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs
index 1b4f4f0..5f986b5 100644
--- a/modules/JiShe.CollectBus.IoTDB/Attribute/TableNameOrTreePathAttribute.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Attributes/TableNameOrTreePathAttribute.cs
@@ -1,6 +1,5 @@
-using JiShe.CollectBus.IoTDB.Enums;
-
-namespace JiShe.CollectBus.IoTDB.Attribute
+
+namespace JiShe.CollectBus.IoTDB.Attributes
{
///
/// IoTDB实体存储路径或表名称,一般用于已经明确的存储路径或表名称,例如日志存储
diff --git a/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs b/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs
new file mode 100644
index 0000000..93bed4f
--- /dev/null
+++ b/modules/JiShe.CollectBus.IoTDB/Exceptions/IoTException.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JiShe.CollectBus.IoTDB.Exceptions
+{
+ ///
+ /// IoTDB异常
+ ///
+ public class IoTException : Exception
+ {
+ public int ErrorCode { get; }
+
+ public IoTException(string message, int errorCode)
+ : base($"{message} (Code: {errorCode})")
+ {
+ ErrorCode = errorCode;
+ }
+ }
+}
diff --git a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj
index 3911399..78b81e3 100644
--- a/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj
+++ b/modules/JiShe.CollectBus.IoTDB/JiShe.CollectBus.IoTDB.csproj
@@ -14,7 +14,6 @@
-
+
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 48bc248..f2d55a5 100644
--- a/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Model/IoTEntity.cs
@@ -1,5 +1,6 @@
using JiShe.CollectBus.Common.Attributes;
-using JiShe.CollectBus.IoTDB.Attribute;
+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 966f226..376b677 100644
--- a/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Model/TableModelSingleMeasuringEntity.cs
@@ -1,20 +1,18 @@
using JiShe.CollectBus.Analyzers.Shared;
-using JiShe.CollectBus.IoTDB.Attribute;
-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
{
///
/// 单项数据键值对
///
[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 719c3c3..56a6c54 100644
--- a/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Model/TreeModelSingleMeasuringEntity.cs
@@ -1,20 +1,18 @@
using JiShe.CollectBus.Analyzers.Shared;
-using JiShe.CollectBus.IoTDB.Attribute;
-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
{
///
/// 单项数据键值对
///
[SingleMeasuring(nameof(SingleMeasuring))]
- public required Tuple SingleMeasuring { get; set; }
+ public required ValueTuple SingleMeasuring { get; set; }
}
}
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 d867674..db86791 100644
--- a/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs
+++ b/modules/JiShe.CollectBus.IoTDB/Provider/IoTDBProvider.cs
@@ -12,7 +12,7 @@ using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Common.Models;
-using JiShe.CollectBus.IoTDB.Attribute;
+using JiShe.CollectBus.IoTDB.Attributes;
using JiShe.CollectBus.IoTDB.Context;
using JiShe.CollectBus.IoTDB.Interface;
using JiShe.CollectBus.IoTDB.Model;
@@ -20,6 +20,8 @@ using JiShe.CollectBus.IoTDB.Options;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
+using JiShe.CollectBus.Analyzers.Shared;
+using JiShe.CollectBus.IoTDB.Exceptions;
namespace JiShe.CollectBus.IoTDB.Provider
{
@@ -176,14 +178,16 @@ namespace JiShe.CollectBus.IoTDB.Provider
///
public async Task GetMetadata() where T : IoTEntity
{
- var columns = CollectColumnMetadata(typeof(T));
+ var accessor = SourceEntityAccessorFactory.GetAccessor();
+
+ var columns = CollectColumnMetadata(accessor);
var metadata = BuildDeviceMetadata(columns);
var metaData = MetadataCache.AddOrUpdate(
typeof(T),
addValueFactory: t => metadata, // 如果键不存在,用此值添加
updateValueFactory: (t, existingValue) =>
{
- var columns = CollectColumnMetadata(t);
+ var columns = CollectColumnMetadata(accessor);
var metadata = BuildDeviceMetadata(columns);
//对现有值 existingValue 进行修改,返回新值
@@ -192,6 +196,8 @@ namespace JiShe.CollectBus.IoTDB.Provider
}
);
+ metadata.EntityType = accessor.EntityType;
+
return await Task.FromResult(metaData);
}
@@ -210,7 +216,7 @@ namespace JiShe.CollectBus.IoTDB.Provider
var query = await BuildQuerySQL(options);
var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query);
-
+
_logger.LogWarning($"{nameof(QueryAsync)} 主题的任务 {options.TableNameOrTreePath} 路径批次{options.PageIndex}任务数据读取完成,共消耗{stopwatch2.ElapsedMilliseconds}毫秒。");
var result = new BusPagedResult
{
@@ -245,146 +251,337 @@ namespace JiShe.CollectBus.IoTDB.Provider
}
}
+ /////
+ ///// 构建Tablet
+ /////
+ /////
+ ///// 表实体
+ ///// 设备元数据
+ /////
+ //private Tablet BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity
+ //{
+ // var timestamps = new List();
+ // var values = new List>();
+ // var devicePaths = new HashSet();
+ // List tempColumnNames = new List();
+ // tempColumnNames.AddRange(metadata.ColumnNames);
+
+ // var accessor = SourceEntityAccessorFactory.GetAccessor();
+
+ // var memberCache = new Dictionary(); // 缓存优化查询
+ // // 预构建成员缓存(Key: NameOrPath)
+ // foreach (var member in accessor.MemberList)
+ // {
+ // memberCache[member.NameOrPath] = member;
+ // }
+
+ // if (accessor.EntityType == null || metadata.EntityType == null)
+ // {
+ // throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定,属于异常情况,-101");
+ // }
+
+ // if (metadata.EntityType != accessor.EntityType)
+ // {
+ // throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致,属于异常情况,-102");
+ // }
+
+ // if (metadata.EntityType == EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true)
+ // {
+ // throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接,属于异常情况,-103");
+ // }
+ // else if (metadata.EntityType == EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false)
+ // {
+ // throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接,属于异常情况,-104");
+ // }
+
+ // string tableNameOrTreePath = string.Empty;
+ // var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute();
+ // if (tableNameOrTreePathAttribute != null)
+ // {
+ // tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
+ // }
+
+ // foreach (var entity in entities)
+ // {
+ // timestamps.Add(entity.Timestamps);
+ // var rowValues = new List
/// 已解析的设备数据元数据
/// 表名称
+ /// 数据列集合
/// 数据集合
/// 时间戳集合
///
- private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List> values, List timestamps)
+ private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List columns,List> values, List timestamps)
{
var tablet = new Tablet(
tableName,
- metadata.ColumnNames,
+ columns,
metadata.ColumnCategories,
metadata.DataTypes,
values,
@@ -547,14 +746,14 @@ namespace JiShe.CollectBus.IoTDB.Provider
var results = new List();
var metadata = await GetMetadata();
- var properties = typeof(T).GetProperties();
+ var accessor = SourceEntityAccessorFactory.GetAccessor();
+ var memberCache = BuildMemberCache(accessor);
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);
+
while (dataSet.HasNext() && results.Count < pageSize)
{
@@ -570,20 +769,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));
- }
- else
- {
- typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue);
- }
+ dynamic tempValue = GetTSDataValue(tSDataType, value);
+
+ if (measurement.ToLower().EndsWith("time"))
+ {
+ member.Setter(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds));
+ }
+ else
+ {
+ member.Setter(entity, tempValue);
}
}
@@ -598,72 +797,57 @@ namespace JiShe.CollectBus.IoTDB.Provider
///
/// 获取设备元数据的列
///
- ///
+ ///
///
- private List CollectColumnMetadata(Type type)
+ private List CollectColumnMetadata(ISourceEntityAccessor accessor)
{
var columns = new List();
+ var memberCache = BuildMemberCache(accessor);
- foreach (var prop in type.GetProperties())
+ foreach (var member in accessor.MemberList)
{
+ // 过滤元组子项
+ if (member.NameOrPath.Contains(".Item")) continue;
- string typeName = string.Empty;
+ // 类型名称处理
+ Type declaredType = member.DeclaredType;
+ var underlyingType = Nullable.GetUnderlyingType(declaredType);
+ string declaredTypeName = underlyingType?.Name ?? member.DeclaredTypeName;
- Type declaredType = prop.PropertyType;
- // 处理可空类型
- 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);
- typeName = underlyingType.Name;
+ column = new ColumnInfo(member.NameOrPath, ColumnCategory.TAG, GetDataTypeFromTypeName(declaredTypeName), false);
}
- else
+ else if (attrColumn != null)
{
- typeName = declaredType.Name;
+ column = new ColumnInfo(member.NameOrPath, ColumnCategory.ATTRIBUTE, GetDataTypeFromTypeName(declaredTypeName), false);
+ }
+ else if (fieldColumn != null)
+ {
+ column = new ColumnInfo(member.NameOrPath, ColumnCategory.FIELD, GetDataTypeFromTypeName(declaredTypeName), false);
}
- //先获取Tag标签和属性标签
- ColumnInfo? column = prop.GetCustomAttribute() is not null ? new ColumnInfo(
- name: prop.Name,
- category: ColumnCategory.TAG,
- dataType: GetDataTypeFromTypeName(typeName),
- false
- ) : prop.GetCustomAttribute() is not null ? new ColumnInfo(
- prop.Name,
- ColumnCategory.ATTRIBUTE,
- GetDataTypeFromTypeName(typeName),
- false
- ) : prop.GetCustomAttribute() is not null ? new ColumnInfo(
- prop.Name,
- ColumnCategory.FIELD,
- GetDataTypeFromTypeName(typeName),
- false)
- : null;
-
- //最先检查是不是单侧点模式
- SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute();
-
- if (singleMeasuringAttribute != null && column == null)
+ // 单测模式处理
+ if (singleMeasuringAttr != null && column == null)
{
- //warning: 单侧点模式注意事项
- //Entity实体 字段类型是 Tuple,Item1=>测点名称,Item2=>测点值,泛型
- //只有一个Filed字段。
- //MeasuringName 默认为 SingleMeasuringAttribute.FieldName,以便于在获取对应的Value的时候重置为 Item1 的值。
-
- Type tupleType = prop.PropertyType;
- Type[] tupleArgs = tupleType.GetGenericArguments();
-
- column = new ColumnInfo(
- singleMeasuringAttribute.FieldName,
- ColumnCategory.FIELD,
- GetDataTypeFromTypeName(tupleArgs[1].Name),
- true
- );
+ var tupleItemKey = $"{member.NameOrPath}.Item2";
+ if (!memberCache.TryGetValue(tupleItemKey, out var tupleMember))
+ {
+ throw new Exception($"{nameof(CollectColumnMetadata)} {accessor.EntityName} {member.NameOrPath} 单侧点属性解析异常");
+ }
+ 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;
}
@@ -693,15 +877,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;
}
@@ -832,5 +1007,21 @@ namespace JiShe.CollectBus.IoTDB.Provider
TSDataType.STRING => Convert.ToString(value),
_ => Convert.ToString(value)
};
+
+ ///
+ /// 缓存实体属性信息
+ ///
+ ///
+ ///
+ ///
+ private Dictionary BuildMemberCache(ISourceEntityAccessor accessor)
+ {
+ var cache = new Dictionary(StringComparer.Ordinal);
+ foreach (var member in accessor.MemberList)
+ {
+ cache[member.NameOrPath] = member;
+ }
+ return cache;
+ }
}
}
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs
index 5c2e890..27fd11f 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_00H/AFN0_F2_Analysis.cs
@@ -37,6 +37,9 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_00H
TimeDensity = -1
};
result?.Invoke(dto);
+#if DEBUG
+ _logger.LogWarning($"全部否认:{input.A.Code}-{input.DT.Fn}-{input.BaseHexMessage.HexMessageString}");
+#endif
return Task.FromResult(true);
}
catch (Exception ex)
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs
index 4eb05ad..a7538ca 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F129_Analysis.cs
@@ -33,7 +33,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
ArgumentNullException.ThrowIfNull(input.A.A3?.D1_D7);
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -48,7 +48,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
TimeDensity = 0
};
List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
- List> list = GenerateFinalResult(2, datas, "正向有功电能示值", input.AFN_FC.AFN, input.DT.Fn);
+ List> list = GenerateFinalResult(2, datas, "正向有功电能示值", input.AFN_FC.AFN, input.DT.Fn);
unitDataAnalysis.Data= list;
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
@@ -90,22 +90,32 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
}
#endregion
- public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
+ public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
{
- List> list = new List>();
+ List> list = new List>();
for (int i = index; i < data.Count; i++)
{
- AnalysisBaseDto meter = new AnalysisBaseDto();
-
- decimal value = 0;
+ AnalysisBaseDto meter = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
+ {
+ meter.ErrorCodeMsg= errorCode.Item2;
meter.ValidData = false;
+ }
else
- decimal.TryParse(data[i], out value);
- meter.DataValue = value;
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ meter.DataValue = value;
+ }
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
- meter.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
+ string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
+ if (DateTime.TryParse(timeSpan, out DateTime readingDate))
+ {
+ meter.TimeSpan = readingDate;
+ }
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs
index cce2df4..59ae0fc 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F130_Analysis.cs
@@ -31,8 +31,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
- List> list = GenerateFinalResult(2, datas, "正向无功电能示值", input.AFN_FC.AFN, input.DT.Fn);
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ List> list = GenerateFinalResult(2, datas, "正向无功电能示值", input.AFN_FC.AFN, input.DT.Fn);
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -78,21 +78,30 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
}
return values;
}
- public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
+ public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
{
- List> list = new List>();
+ List> list = new List>();
for (int i = index; i < data.Count; i++)
{
- AnalysisBaseDto meter = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto meter = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
+ {
+ meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
+ }
else
- decimal.TryParse(data[i], out value);
- meter.DataValue = value;
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ meter.DataValue = value;
+ }
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
- meter.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
+ string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
+ if(DateTime.TryParse(timeSpan, out DateTime readingDate))
+ meter.TimeSpan = readingDate;
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs
index 4cbb5b5..9b57ea1 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F131_Analysis.cs
@@ -6,6 +6,8 @@ using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
@@ -30,8 +32,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
- List> list = GenerateFinalResult(2, datas, "反向有功总电能示值", input.AFN_FC.AFN, input.DT.Fn);
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ List> list = GenerateFinalResult(2, datas, "反向有功总电能示值", input.AFN_FC.AFN, input.DT.Fn);
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -78,21 +80,30 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
}
return values;
}
- public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
+ public List> GenerateFinalResult(int index, List data, string filedDesc = "", int afn = 0, int fn = 0)
{
- List> list = new List>();
+ List> list = new List>();
for (int i = index; i < data.Count; i++)
{
- AnalysisBaseDto meter = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto meter = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
+ {
+ meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
+ }
else
- decimal.TryParse(data[i], out value);
- meter.DataValue = value;
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ meter.DataValue = value;
+ }
meter.DataType = $"{afn.ToString().PadLeft(2, '0')}_{fn}_{i - index}";
- meter.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
+ string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
+ if(DateTime.TryParse(timeSpan, out DateTime readTime))
+ meter.TimeSpan = readTime;
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs
index 59096de..70db824 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F132_Analysis.cs
@@ -7,6 +7,7 @@ using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
{
@@ -34,9 +35,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
-
- List> list = GenerateFinalResult(2, datas, "反向无功电能示值", dataType);
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ List> list = GenerateFinalResult(2, datas, "反向无功电能示值", dataType);
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -82,21 +82,33 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
}
return values;
}
- public List> GenerateFinalResult(int index, List data, string dataType, string filedDesc = "")
+ public List> GenerateFinalResult(int index, List data, string dataType, string filedDesc = "")
{
- List> list = new List>();
+ List> list = new List>();
for (int i = index; i < data.Count; i++)
{
- AnalysisBaseDto meter = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto meter = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
+ {
+ meter.ErrorCodeMsg = errorCode.Item2;
meter.ValidData = false;
+ }
else
- decimal.TryParse(data[i], out value);
- meter.DataValue = value;
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ meter.DataValue = value;
+ }
+
meter.DataType = $"{dataType}_{i - index}";
- meter.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
+ string timeSpan = $"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00";
+ if (DateTime.TryParse(timeSpan,out DateTime readingDate))
+ {
+ meter.TimeSpan = readingDate;
+ }
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs
index e0d143b..ecbaef0 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F145_Analysis.cs
@@ -35,8 +35,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
List datas = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- AnalysisBaseDto data = GenerateFinalResult(datas, "当月正向有功最大需量及发生时间", dataType);
- UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis>
+ AnalysisBaseDto data = GenerateFinalResult(datas, "当月正向有功最大需量及发生时间", dataType);
+ UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -96,19 +96,25 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0CH
return values;
}
- public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc,string dataType)
+ public AnalysisBaseDto GenerateFinalResult(List data, string filedDesc,string dataType)
{
- AnalysisBaseDto dto = new AnalysisBaseDto();
-
- decimal value = 0;
+ AnalysisBaseDto dto = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCode = data[2].CheckErrorCode();
if (errorCode != null)
+ {
+ dto.ErrorCodeMsg = errorCode.Item2;
dto.ValidData = false;
+ }
else
- decimal.TryParse(data[2], out value);
-
- dto.DataValue = value;
- string timeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";//$"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)}";
+ {
+ if(decimal.TryParse(data[2], out decimal value))
+ dto.DataValue = value;
+ }
+
+ string timeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
dto.TimeSpan = readingDate;
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs
index 53b0e23..671e625 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F149_Analysis.cs
@@ -38,7 +38,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
List datas = await AnalysisDataUnit(input.UnitData.HexMessageList);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- AnalysisBaseDto data = GenerateFinalResult(datas, dataType,"上月(上一结算日)正向有功最大需量及发生时间");
+ AnalysisBaseDto data = GenerateFinalResult(datas, dataType,"上月(上一结算日)正向有功最大需量及发生时间");
// 查询电表信息
AmmeterInfo ammeterInfo = await _dataStorage.GetMeterInfoAsync(data.DeviceType.ToString(), "15");
if (ammeterInfo != null)
@@ -48,7 +48,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
data.DatabaseBusiID=ammeterInfo.DatabaseBusiID;
data.DeviceAddress= ammeterInfo.AmmerterAddress;
}
- UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis>
+ UnitDataAnalysis> unitDataAnalysis = new UnitDataAnalysis>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -63,7 +63,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
DensityUnit = DensityUnit.Second,
TimeDensity = 0
};
- await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis);
+ await _dataStorage.SaveDataToIotDbAsync(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
@@ -110,10 +110,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
}
return values;
}
- public AnalysisBaseDto GenerateFinalResult(List data,string dataType, string filedDesc = "")
+ public AnalysisBaseDto GenerateFinalResult(List data,string dataType, string filedDesc = "")
{
- AnalysisBaseDto dto = new AnalysisBaseDto();
-
+ AnalysisBaseDto dto = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCodeInfo = data[2].CheckErrorCode();
if (errorCodeInfo != null)
{
@@ -133,7 +135,6 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
else
{
string timeSpan = $"{DateTime.Now.Year}-{data[3].Substring(0, 2)}-{data[3].Substring(2, 2)} {data[3].Substring(4, 2)}:{data[3].Substring(6, 2)}:00";
-
//TODO:时间标
if (!DateTime.TryParse(timeSpan, out DateTime dataTime))
dto.ValidData = false;
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs
index 5758459..e48cdc4 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F188_Analysis.cs
@@ -6,6 +6,7 @@ using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
@@ -34,8 +35,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
ArgumentNullException.ThrowIfNull(input.AFN_FC.AFN);
ArgumentNullException.ThrowIfNull(input.DT.Fn);
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- AnalysisBaseDto data = GenerateFinalResult(input.UnitData.HexMessageList, dataType);
- UnitDataAnalysis> dto = new UnitDataAnalysis>
+ AnalysisBaseDto data = GenerateFinalResult(input.UnitData.HexMessageList, dataType);
+ UnitDataAnalysis> dto = new UnitDataAnalysis>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -58,10 +59,12 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
}
return await Task.FromResult(false);
}
- public AnalysisBaseDto GenerateFinalResult(List hexMessageList,string dataType)
+ public AnalysisBaseDto GenerateFinalResult(List hexMessageList,string dataType)
{
- AnalysisBaseDto dto = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto dto = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.WaterMeter
+ };
var arr = hexMessageList.GetRange(11, 4);
var errorCodeInfo = arr.CheckErrorCode();
if (errorCodeInfo != null)
@@ -70,9 +73,10 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
else
- decimal.TryParse($"{arr[11]}{arr[12]}{arr[13]}.{arr[14]}", out value);
-
- dto.DataValue = value;
+ {
+ if (decimal.TryParse($"{arr[11]}{arr[12]}{arr[13]}.{arr[14]}", out decimal value))
+ dto.DataValue = value;
+ }
dto.DataType = dataType;
dto.FiledDesc = "水示值";
dto.FiledName = dto.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs
index a58c574..4c754e3 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F25_Analysis.cs
@@ -1,11 +1,14 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using Newtonsoft.Json.Linq;
+using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
@@ -32,13 +35,15 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
ArgumentNullException.ThrowIfNull(input);
ArgumentNullException.ThrowIfNull(input.UnitData?.HexMessageList);
List remarks = new List() { "当前总有功功率", "当前A相有功功率", "当前B相有功功率", "当前C相有功功率", "当前总无功功率", "当前A相无功功率", "当前B相无功功率", "当前C相无功功率", "当前总功率因数", "当前A相功率因数", "当前B相功率因数", "当前C相功率因数", "当前A相电压", "当前B相电压", "当前C相电压", "当前A相电流", "当前C相电流", "当前 C相电流", "当前零序电流", "当前总视在功率", "当前A相视在功率", "当前B相视在功率", "当前C相视在功率" };
- List> list = new List>();
+ List> list = new List>();
List data = await AnalysisDataUnitAsync(input.UnitData.HexMessageList);
for (int i = 1; i < data.Count; i++)
{
- AnalysisBaseDto dto = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto dto = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCodeInfo = data[i].CheckErrorCode();
if (errorCodeInfo != null)
{
@@ -46,15 +51,18 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
dto.ErrorCodeMsg = errorCodeInfo.Item2;
}
else
- decimal.TryParse(data[i], out value);
- dto.DataValue = value;
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ dto.DataValue = value;
+ }
+
dto.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{DataType[i-1]}";
- dto.FiledName = DataType[i - 1];
+ dto.FiledName = DataType[i - 1].GetDataFieldByGatherDataType() ?? string.Empty;
dto.TimeSpan = Convert.ToDateTime($"{data[0].Substring(0, 4)}-{data[0].Substring(4, 2)}-{data[0].Substring(6, 2)} {data[0].Substring(8, 2)}:{data[0].Substring(10, 2)}:00");
dto.FiledDesc = remarks[i - 1];
list.Add(dto);
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs
index 2bc496f..5bac5c7 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F2_Analysis.cs
@@ -6,6 +6,8 @@ using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+using System.Diagnostics.Metrics;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
@@ -71,7 +73,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
await _analysisStrategyContext.ExecuteAsync>(nameof(Appendix_A1), arr, (value) =>
{
- dto.DataValue = value;
+ var data = (Tuple)value;
+ dto.DataValue = $"{data.Item1} {data.Item2}";
});
}
dto.DataType = dataType;
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs
index b639f0d..f4dd742 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0CH/AFN12_F49_Analysis.cs
@@ -1,11 +1,13 @@
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using JiShe.CollectBus.Protocol.Dto;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.T37612012.Appendix;
using JiShe.CollectBus.Protocol3761;
using Microsoft.Extensions.Logging;
+using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
{
@@ -33,27 +35,30 @@ namespace JiShe.CollectBus.Protocol.T37612012.AFN_0CH
List data = await AnalysisDataUnitAsync(input.UnitData?.HexMessageList!);
List remarks = new List() { "Uab/Ua 相位角", "Ub 相位角", "Ucb/Uc 相位角", "Ia 相位角", "Ib 相位角", "Ic 相位角" };
- List> list = new List>();
+ List> list = new List>();
for (int i = 0; i < data.Count; i++)
{
- AnalysisBaseDto dto = new AnalysisBaseDto();
- decimal value = 0;
+ AnalysisBaseDto dto = new AnalysisBaseDto
+ {
+ DeviceType = MeterTypeEnum.Ammeter
+ };
var errorCodeInfo = data[i].CheckErrorCode();
if (errorCodeInfo != null)
{
dto.ValidData = false;
dto.ErrorCodeMsg = errorCodeInfo.Item2;
- }
+ }
else
- decimal.TryParse(data[i], out value);
- dto.DataValue = value;
-
+ {
+ if(decimal.TryParse(data[i], out decimal value))
+ dto.DataValue = value;
+ }
dto.DataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}_{DataType[i]}";
- dto.FiledName = DataType[i];
+ dto.FiledName = dto.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
dto.FiledDesc= remarks[i];
list.Add(dto);
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs
index 084338b..3df913f 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F100_Analysis.cs
@@ -38,7 +38,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能量");
+ List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向无功总电能量");
if (data.Count > 0)
{
@@ -56,7 +56,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
}
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -71,7 +71,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime
};
- await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
+ await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs
index 5457f1d..f4d4c0a 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F101_Analysis.cs
@@ -37,7 +37,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
int density = Convert.ToInt32(Convert.ToInt32(datas[1]).GetEnumDescription(typeof(DensityEnums)));
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能示值");
+ List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向有功总电能示值");
if (data.Count > 0)
{
// 查询电表信息
@@ -53,7 +53,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
});
}
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -68,7 +68,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime
};
- await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
+ await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs
index 9a10a3d..4e02149 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F102_Analysis.cs
@@ -38,7 +38,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能示值");
+ List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "正向无功总电能示值");
if (data.Count > 0)
{
@@ -55,7 +55,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
});
}
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -70,7 +70,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime
};
- await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
+ await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
result?.Invoke(unitDataAnalysis);
return await Task.FromResult(true);
}
diff --git a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs
index 790f871..94faa02 100644
--- a/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs
+++ b/protocols/JiShe.CollectBus.Protocol.T37612012/AnalysisData/AFN_0DH/AFN13_F103_Analysis.cs
@@ -38,7 +38,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
string dataType = $"{input.AFN_FC.AFN.HexToDecStr().PadLeft(2, '0')}_{input.DT.Fn}";
- List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向有功总电能示值");
+ List> data = datas.GenerateFinalResultTd_c(3, density, dataType, "反向有功总电能示值");
if (data.Count > 0)
{
@@ -55,7 +55,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
});
}
}
- UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
+ UnitDataAnalysis>> unitDataAnalysis = new UnitDataAnalysis>>
{
Code = input.A.Code!,
AFN = input.AFN_FC.AFN,
@@ -70,7 +70,7 @@ namespace JiShe.CollectBus.Protocol.T37612012.AnalysisData.AFN_0DH
DensityUnit = DensityUnit.Minute,
ReceivedTime = input.ReceivedTime
};
- await _dataStorage.SaveMultipleDataToIotDbAsync(unitDataAnalysis);
+ await _dataStorage.SaveMultipleDataToIotDbAsync