修复15分钟任务Kafka主题异常的问题,新增增量源码工厂类

This commit is contained in:
ChenYi 2025-05-06 23:46:12 +08:00
parent 01264dd3ec
commit 53e6bb252a
4 changed files with 178 additions and 50 deletions

View File

@ -14,17 +14,14 @@ namespace JiShe.CollectBus.IncrementalGenerator
public class ComplexTypeSourceAnalyzers : IIncrementalGenerator public class ComplexTypeSourceAnalyzers : IIncrementalGenerator
{ {
private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute"; private const string AttributeFullName = "JiShe.CollectBus.Analyzers.Shared.SourceAnalyzersAttribute";
private const string SourceEntityAccessorFactoryNamespace = "JiShe.CollectBus.Analyzers.Shared";
public void Initialize(IncrementalGeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
//Debugger.Launch(); //Debugger.Launch();
context.RegisterPostInitializationOutput(ctx =>
{
ctx.AddSource("GeneratorInit.g.cs", "// Initialization Marker");
});
// 步骤1筛选带有 [GenerateAccessors] 的类 // 步骤1筛选带有 [SourceAnalyzers] 的类
var classDeclarations = context.SyntaxProvider var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider( .CreateSyntaxProvider(
predicate: static (s, _) => IsClassWithAttribute(s), predicate: static (s, _) => IsClassWithAttribute(s),
@ -40,7 +37,6 @@ namespace JiShe.CollectBus.IncrementalGenerator
private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0; private static bool IsClassWithAttribute(SyntaxNode node) => node is ClassDeclarationSyntax cds && cds.AttributeLists.Count > 0;
private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context) private static ClassDeclarationSyntax GetClassDeclaration(GeneratorSyntaxContext context)
{ {
var classDecl = (ClassDeclarationSyntax)context.Node; var classDecl = (ClassDeclarationSyntax)context.Node;
@ -76,6 +72,12 @@ namespace JiShe.CollectBus.IncrementalGenerator
} }
} }
/// <summary>
/// 生成代码
/// </summary>
/// <param name="compilation"></param>
/// <param name="classes"></param>
/// <param name="context"></param>
private static void GenerateCode( private static void GenerateCode(
Compilation compilation, Compilation compilation,
IEnumerable<ClassDeclarationSyntax> classes, IEnumerable<ClassDeclarationSyntax> classes,
@ -86,8 +88,8 @@ namespace JiShe.CollectBus.IncrementalGenerator
if (!classes.Any()) if (!classes.Any())
{ {
context.ReportDiagnostic(Diagnostic.Create( context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("GEN002", "No Targets", new DiagnosticDescriptor("GEN002", "没有目标类",
"No classes with [GenerateAccessors] found", "Debug", DiagnosticSeverity.Warning, true), "没有找到SourceAnalyzers标记的类", "Debug", DiagnosticSeverity.Warning, true),
Location.None)); Location.None));
} }
@ -99,46 +101,66 @@ namespace JiShe.CollectBus.IncrementalGenerator
if (classSymbol == null || !processedTypes.Add(classSymbol)) if (classSymbol == null || !processedTypes.Add(classSymbol))
{ {
context.ReportDiagnostic(Diagnostic.Create( context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("GEN003", "Invalid Symbol", new DiagnosticDescriptor("GEN003", "无效符号",
$"Class symbol is null for {classDecl.Identifier.Text}", "Error", DiagnosticSeverity.Error, true), $"类名称为{classDecl.Identifier.Text} 符号为空", "Error", DiagnosticSeverity.Error, true),
Location.None)); Location.None));
continue; continue;
} }
context.ReportDiagnostic(Diagnostic.Create( //context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor( //new DiagnosticDescriptor(
"PA001", // "PA001",
"Generated Accessors", // "Generated Accessors",
$"Generating accessors for {classSymbol.Name}", // $"Generating accessors for {classSymbol.Name}",
"Performance", // "Performance",
DiagnosticSeverity.Info, // DiagnosticSeverity.Info,
true), // true),
Location.None)); //Location.None));
// 新增:输出继承链信息 //// 新增:输出继承链信息
context.ReportDiagnostic(Diagnostic.Create( //context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy", // new DiagnosticDescriptor("HIERARCHY", "Class Hierarchy",
$"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}", // $"Processing class: {classSymbol.Name}, BaseType: {classSymbol.BaseType?.Name}",
"Debug", DiagnosticSeverity.Info, true), // "Debug", DiagnosticSeverity.Info, true),
Location.None)); // Location.None));
context.ReportDiagnostic(Diagnostic.Create( //context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor("PA002", "Class Found", //new DiagnosticDescriptor("PA002", "Class Found",
$"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, true), //$"Processing class: {classSymbol.Name}", "Debug", DiagnosticSeverity.Warning, true),
Location.None)); //Location.None));
var code = BuildAccessorsForType(classSymbol, compilation, processedTypes); var code = BuildAccessorsForType(classSymbol, compilation, processedTypes);
System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出 //System.Diagnostics.Debug.WriteLine($"Generated code for {classSymbol.Name}:\n{code}"); // 调试输出
context.AddSource($"{classSymbol.Name}Extension.g.cs", code); context.AddSource($"{classSymbol.Name}Extension.g.cs", code);
var code3 = BuildAccessorsForType2(classSymbol, compilation, processedTypes);
context.AddSource($"{classSymbol.Name}Accessor.g.cs", code3);
//code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
//if (classSymbol.ContainingNamespace.ToDisplayString() == "JiShe.CollectBus.IoTDB")
//{
//}
} }
// 生成工厂注册代码
context.AddSource("SourceEntityAccessorFactory.g.cs", BuildFactoryCode());
} }
/// <summary>
/// 构建类的属性访问器代码
/// </summary>
/// <param name="classSymbol"></param>
/// <param name="compilation"></param>
/// <param name="processedTypes"></param>
/// <returns></returns>
private static string BuildAccessorsForType( private static string BuildAccessorsForType(
INamedTypeSymbol classSymbol, INamedTypeSymbol classSymbol,
Compilation compilation, Compilation compilation,
HashSet<ITypeSymbol> processedTypes) HashSet<ITypeSymbol> processedTypes)
{ {
var code = new StringBuilder(); var code = new StringBuilder();
code.AppendLine("#pragma warning disable CS0419 // 禁用警告"); code.AppendLine("#pragma warning disable CS0419 // 禁用警告");
@ -151,25 +173,67 @@ namespace JiShe.CollectBus.IncrementalGenerator
code.AppendLine($"public static class {classSymbol.Name}Extension{GetGenericParams(classSymbol)}"); code.AppendLine($"public static class {classSymbol.Name}Extension{GetGenericParams(classSymbol)}");
code.AppendLine("{"); code.AppendLine("{");
//foreach (var prop in classSymbol.GetMembers().OfType<IPropertySymbol>())
//{
// if (prop.IsIndexer) continue;
// GeneratePropertyAccessors(prop, code, compilation, processedTypes);
//}
foreach (var prop in GetAllPropertiesInHierarchy(classSymbol)) foreach (var prop in GetAllPropertiesInHierarchy(classSymbol))
{ {
if (prop.IsIndexer) continue; if (prop.IsIndexer) continue;
GeneratePropertyAccessors(prop, code, compilation, processedTypes); GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes);
} }
code.AppendLine("}"); code.AppendLine("}");
return code.ToString(); return code.ToString();
} }
//private static string GetGenericParams(INamedTypeSymbol symbol) /// <summary>
// => symbol.IsGenericType ? $"<{string.Join(", ", symbol.TypeParameters.Select(t => t.Name))}>" : ""; /// 构建类的属性访问器代码
/// </summary>
/// <param name="classSymbol"></param>
/// <param name="compilation"></param>
/// <param name="processedTypes"></param>
/// <returns></returns>
private static string BuildAccessorsForType2(
INamedTypeSymbol classSymbol,
Compilation compilation,
HashSet<ITypeSymbol> processedTypes)
{
var code = new StringBuilder();
code.AppendLine("#pragma warning disable CS0419 // 禁用警告");
code.AppendLine("// Generated code for " + classSymbol.Name);
code.AppendLine("// <auto-generated/>");
code.AppendLine("#nullable enable");
code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()};");
code.AppendLine();
code.AppendLine($"public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>");
code.AppendLine("{");
foreach (var prop in GetAllPropertiesInHierarchy(classSymbol))
{
if (prop.IsIndexer) continue;
GeneratePropertyAccessorsForType(prop, code, compilation, processedTypes);
}
code.AppendLine("}");
//var code3 = $@"
// public sealed class {classSymbol.Name}Accessor : ISourceEntityAccessor<{classSymbol.Name}>
// {{
// public object GetPropertyValue({classSymbol.Name} entity, string propName) => propName switch
// {{
// {GeneratePropertyCases(classSymbol)}
// _ => throw new ArgumentException(""无效属性名"")
// }};
// {GenerateTupleSupport(classSymbol)}
// }}";
return code.ToString();
}
/// <summary>
/// 获取泛型参数
/// </summary>
/// <param name="symbol"></param>
/// <returns></returns>
public static string GetGenericParams(INamedTypeSymbol symbol) public static string GetGenericParams(INamedTypeSymbol symbol)
{ {
if (!symbol.IsGenericType) return ""; if (!symbol.IsGenericType) return "";
@ -177,13 +241,20 @@ namespace JiShe.CollectBus.IncrementalGenerator
return $"<{string.Join(", ", parameters)}>"; return $"<{string.Join(", ", parameters)}>";
} }
private static void GeneratePropertyAccessors( /// <summary>
/// 生成属性访问器代码
/// </summary>
/// <param name="prop"></param>
/// <param name="code"></param>
/// <param name="compilation"></param>
/// <param name="processedTypes"></param>
private static void GeneratePropertyAccessorsForType(
IPropertySymbol prop, IPropertySymbol prop,
StringBuilder code, StringBuilder code,
Compilation compilation, Compilation compilation,
HashSet<ITypeSymbol> processedTypes) HashSet<ITypeSymbol> processedTypes)
{ {
// 关键修复点1安全类型转换 // 安全类型转换
if (prop.Type is not ITypeSymbol propType) return; if (prop.Type is not ITypeSymbol propType) return;
code.AppendLine($" // Processing property: {prop.Name}"); code.AppendLine($" // Processing property: {prop.Name}");
@ -200,6 +271,12 @@ namespace JiShe.CollectBus.IncrementalGenerator
} }
} }
/// <summary>
/// 处理元组类型
/// </summary>
/// <param name="prop"></param>
/// <param name="tupleType"></param>
/// <param name="code"></param>
private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code) private static void GenerateTupleAccessors(IPropertySymbol prop, INamedTypeSymbol tupleType, StringBuilder code)
{ {
var elements = tupleType.TupleElements; var elements = tupleType.TupleElements;
@ -222,6 +299,12 @@ namespace JiShe.CollectBus.IncrementalGenerator
} }
} }
/// <summary>
/// 生成标准属性的访问器
/// </summary>
/// <param name="prop"></param>
/// <param name="propType"></param>
/// <param name="code"></param>
private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code) private static void GenerateStandardAccessors(IPropertySymbol prop, INamedTypeSymbol propType, StringBuilder code)
{ {
var parentType = prop.ContainingType.ToDisplayString(); var parentType = prop.ContainingType.ToDisplayString();
@ -233,6 +316,13 @@ namespace JiShe.CollectBus.IncrementalGenerator
} }
} }
/// <summary>
/// 处理嵌套类型
/// </summary>
/// <param name="typeSymbol"></param>
/// <param name="compilation"></param>
/// <param name="processedTypes"></param>
private static void ProcessNestedType(ITypeSymbol typeSymbol, Compilation compilation, HashSet<ITypeSymbol> processedTypes) private static void ProcessNestedType(ITypeSymbol typeSymbol, Compilation compilation, HashSet<ITypeSymbol> processedTypes)
{ {
if (typeSymbol is not INamedTypeSymbol namedType) return; if (typeSymbol is not INamedTypeSymbol namedType) return;
@ -242,6 +332,11 @@ namespace JiShe.CollectBus.IncrementalGenerator
var code = BuildAccessorsForType(namedType, compilation, processedTypes); var code = BuildAccessorsForType(namedType, compilation, processedTypes);
} }
/// <summary>
/// 处理嵌套类型
/// </summary>
/// <param name="symbol"></param>
/// <returns></returns>
private static bool ShouldProcessNestedType(INamedTypeSymbol symbol) private static bool ShouldProcessNestedType(INamedTypeSymbol symbol)
{ {
return symbol.DeclaredAccessibility == Accessibility.Public && return symbol.DeclaredAccessibility == Accessibility.Public &&
@ -250,5 +345,33 @@ namespace JiShe.CollectBus.IncrementalGenerator
!symbol.IsImplicitlyDeclared && !symbol.IsImplicitlyDeclared &&
!symbol.Name.StartsWith("<"); !symbol.Name.StartsWith("<");
} }
/// <summary>
/// 生成扩展类工厂代码
/// </summary>
/// <returns></returns>
private static string BuildFactoryCode()
{
return """
using System;
using System.Collections.Concurrent;
namespace JiShe.CollectBus.Analyzers.Shared;
public static class SourceEntityAccessorFactory
{
private static readonly ConcurrentDictionary<Type, object> _accessors = new();
public static ISourceEntityAccessor<T> GetAccessor<T>()
{
if (!_accessors.TryGetValue(typeof(T), out var accessor))
{
accessor = Activator.CreateInstance(
Type.GetType($"{typeof(T).Namespace}.{typeof(T).Name}Accessor")!)!;
_accessors.TryAdd(typeof(T), accessor);
}
return (ISourceEntityAccessor<T>)accessor!;
}
}
""";
}
} }
} }

View File

@ -53,6 +53,10 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS
[HttpGet] [HttpGet]
public async Task UseSessionPool(long testTime) public async Task UseSessionPool(long testTime)
{ {
var dataTime = DateTime.Now;
List<string> values = new List<string>() { $"{dataTime:yy}", $"{dataTime:MM}", $"{dataTime:dd}", $"{dataTime:HH}", $"{dataTime:mm}", };
ElectricityMeterTreeModel meter = new ElectricityMeterTreeModel() ElectricityMeterTreeModel meter = new ElectricityMeterTreeModel()
{ {
@ -67,6 +71,7 @@ public class SampleAppService : CollectBusAppService, ISampleAppService, IKafkaS
Timestamps = testTime// DateTimeOffset.UtcNow.ToUnixTimeNanoseconds()//testTime.GetDateTimeOffset().ToUnixTimeNanoseconds(), Timestamps = testTime// DateTimeOffset.UtcNow.ToUnixTimeNanoseconds()//testTime.GetDateTimeOffset().ToUnixTimeNanoseconds(),
}; };
//ElectricityMeterTreeModelExtension.GetCurrent() //ElectricityMeterTreeModelExtension.GetCurrent()
//SourceEntityAccessorFactory.SetCurrent(meter);
await _iotDBProvider.InsertAsync(meter); await _iotDBProvider.InsertAsync(meter);
} }

View File

@ -262,7 +262,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
//_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); //_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}");
return; return;
} }
_ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask)); _ = _dataChannelManage.ScheduledMeterTaskWriterAsync(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerFifteenMinuteIssuedEventName, tempTask));
}); });
} }
else if (meteryType == MeterTypeEnum.WaterMeter.ToString()) else if (meteryType == MeterTypeEnum.WaterMeter.ToString())

View File

@ -2,9 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace JiShe.CollectBus.Analyzers namespace JiShe.CollectBus.Analyzers.Shared
{ {
public interface ISourceAnalyzersProvider<T> public interface ISourceEntityAccessor<T>
{ {
/// <summary> /// <summary>
/// 获取属性值 /// 获取属性值