新增报文解析采用策略模式执行解析

This commit is contained in:
zenghongyao 2025-04-22 18:07:47 +08:00
parent 5ca4cbad13
commit 633df21f43
7 changed files with 68 additions and 30 deletions

View File

@ -1,4 +1,5 @@
using JiShe.CollectBus.Protocol.Contracts.Interfaces; using JiShe.CollectBus.Protocol.Contracts.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -8,18 +9,27 @@ using System.Threading.Tasks;
namespace JiShe.CollectBus.Protocol.Contracts namespace JiShe.CollectBus.Protocol.Contracts
{ {
public class AnalysisStrategyContext<TInput, TResult> public class AnalysisStrategyContext
{ {
private readonly IAnalysisStrategy<TInput, TResult> _analysisStrategy; private readonly IServiceProvider _provider;
public AnalysisStrategyContext(IAnalysisStrategy<TInput, TResult> analysisStrategy) public AnalysisStrategyContext(IServiceProvider provider) => _provider = provider;
/// <summary>
/// 执行策略
/// </summary>
/// <typeparam name="TInput"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="type"></param>
/// <param name="input"></param>
/// <returns></returns>
public Task<TResult> ExecuteAsync<TInput, TResult>(string type, TInput input)
{ {
_analysisStrategy = analysisStrategy; var factory = _provider.GetRequiredService<Func<string, Type, Type, object>>();
var strategy = (IAnalysisStrategy<TInput, TResult>)factory(type, typeof(TInput), typeof(TResult));
return strategy.ExecuteAsync(input);
}
} }
public Task<TResult> ExecuteAnalysisStrategy(TInput input)
{
return _analysisStrategy.ExecuteAsync(input);
}
}
} }

View File

@ -14,6 +14,10 @@ namespace JiShe.CollectBus.Protocol.AnalysisData.AFN_00H
{ {
public class AFN0_F1_Analysis: IAnalysisStrategy<TB3761, AFN0_F1_AnalysisDto> public class AFN0_F1_Analysis: IAnalysisStrategy<TB3761, AFN0_F1_AnalysisDto>
{ {
public static string StrategyType => nameof(AFN0_F1_Analysis);
public static Type InputType => typeof(TB3761);
public static Type ResultType => typeof(AFN0_F1_AnalysisDto);
private readonly ILogger<AFN0_F1_Analysis> _logger; private readonly ILogger<AFN0_F1_Analysis> _logger;
public AFN0_F1_Analysis(ILogger<AFN0_F1_Analysis> logger) public AFN0_F1_Analysis(ILogger<AFN0_F1_Analysis> logger)

View File

@ -1,5 +1,6 @@
using JiShe.CollectBus.Kafka.Internal; using JiShe.CollectBus.Kafka.Internal;
using JiShe.CollectBus.Protocol.AnalysisData; using JiShe.CollectBus.Protocol.AnalysisData;
using JiShe.CollectBus.Protocol.Contracts;
using JiShe.CollectBus.Protocol.Contracts.Abstracts; using JiShe.CollectBus.Protocol.Contracts.Abstracts;
using JiShe.CollectBus.Protocol.Contracts.Interfaces; using JiShe.CollectBus.Protocol.Contracts.Interfaces;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -29,6 +30,10 @@ namespace JiShe.CollectBus.Protocol
public void RegisterProtocolAnalysis(IServiceCollection services) public void RegisterProtocolAnalysis(IServiceCollection services)
{ {
// 扫描并注册所有策略
var strategyMetadata = new Dictionary<(string, Type, Type), Type>();
services.AddTransient<AnalysisStrategyContext>();
// 批量注册 // 批量注册
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
if (string.IsNullOrWhiteSpace(assemblyPath)) if (string.IsNullOrWhiteSpace(assemblyPath))
@ -44,27 +49,44 @@ namespace JiShe.CollectBus.Protocol
.FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName); .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName);
var assembly = existingAssembly ?? Assembly.LoadFrom(file); var assembly = existingAssembly ?? Assembly.LoadFrom(file);
// 实现IAnalysisStrategy接口 // 实现IAnalysisStrategy接口
//var analysisStrategyTypes = assembly.GetTypes().Where(t =>!t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>)));
//i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>))).ToList(); if (analysisStrategyTypes.Count() == 0)
var analysisStrategyTypes = assembly.GetTypes().Where(type =>
typeof(IAnalysisStrategy<,>).IsAssignableFrom(type) &&
!type.IsAbstract && !type.IsInterface).ToList();
if (analysisStrategyTypes.Count == 0)
continue; continue;
foreach (var analysisStrategyType in analysisStrategyTypes) foreach (var analysisStrategyType in analysisStrategyTypes)
{ {
// 取所有接口 // 通过反射获取静态元数据
//var interfaceTypes = analysisStrategyType.GetInterfaces() var strategyType = analysisStrategyType.Name;
// .Where(i => i.IsGenericType && var genericArgs = analysisStrategyType.GetInterface("IAnalysisStrategy`2")!.GetGenericArguments();
// i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<,>)); var inputType = genericArgs[0];
//foreach (var interfaceType in interfaceTypes) var resultType = genericArgs[1];
//{ // 注册策略实现
// services.AddKeyedTransient(analysisStrategyType, nameof(analysisStrategyType)); services.AddTransient(analysisStrategyType);
//} strategyMetadata[(strategyType, inputType, resultType)] = analysisStrategyType;
services.AddKeyedTransient(analysisStrategyType, nameof(analysisStrategyType));
} }
} }
// 注册元数据字典
services.AddSingleton(strategyMetadata);
// 注册策略解析工厂
services.AddTransient<Func<string, Type, Type, object?>>(provider => (name, inputType, resultType) =>
{
var metadata = provider.GetRequiredService<Dictionary<(string, Type, Type), Type>>();
if (metadata.TryGetValue((name, inputType, resultType), out var strategyType))
{
return provider.GetRequiredService(strategyType);
}
else
{
var logger= provider.GetRequiredService<ILogger<AnalysisStrategyContext>>();
logger.LogWarning($"未能找到解析策略:{name}-{inputType}-{resultType}");
return null;
}
});
} }
} }
} }

View File

@ -248,8 +248,8 @@ namespace JiShe.CollectBus.ScheduledMeterReading
timer1.Stop(); timer1.Stop();
_logger.LogError($"读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒"); _logger.LogError($"读取数据总共花费时间{timer1.ElapsedMilliseconds}毫秒");
//DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions); DeviceGroupBalanceControl.InitializeCache(focusAddressDataLista, _kafkaOptions.NumPartitions);
//return; return;
#else #else
var meterInfos = await GetAmmeterInfoList(gatherCode); var meterInfos = await GetAmmeterInfoList(gatherCode);
#endif #endif

View File

@ -219,7 +219,7 @@ namespace JiShe.CollectBus.Subscribers
} }
[KafkaSubscribe(ProtocolConst.SubscriberAFN01HReceivedEventNameTemp)] [KafkaSubscribe(ProtocolConst.SubscriberAFN02HReceivedEventNameTemp)]
public async Task<ISubscribeAck> ReceivedAFN00Event(MessageReceived receivedMessage) public async Task<ISubscribeAck> ReceivedAFN00Event(MessageReceived receivedMessage)
{ {
@ -241,11 +241,12 @@ namespace JiShe.CollectBus.Subscribers
Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}"); Logger.LogError($"数据解析失败:{receivedMessage.Serialize()}");
return SubscribeAck.Success(); return SubscribeAck.Success();
} }
//string serverName = $"AFN{tB3761.AFN_FC.AFN}_F{tB3761.DT.Fn}_Analysis"; string serverName = $"AFN{tB3761.AFN_FC.AFN}_F{tB3761.DT.Fn}_Analysis";
//var analysisStrategy = _serviceProvider.GetKeyedService<IAnalysisStrategy>($"AFN0_F1_Analysis"); //var analysisStrategy = _serviceProvider.GetKeyedService<IAnalysisStrategy>($"AFN0_F1_Analysis");
//var data = await analysisStrategy.ExecuteAsync<UnitDataDto<AFN0_F1_AnalysisDto>>(tB3761); //var data = await analysisStrategy.ExecuteAsync<UnitDataDto<AFN0_F1_AnalysisDto>>(tB3761);
var executor = _serviceProvider.GetRequiredService<AnalysisStrategyContext>();
AFN0_F1_AnalysisDto aFN0_F1_AnalysisDto= await executor.ExecuteAsync<TB3761,AFN0_F1_AnalysisDto>("AFN0_F1_Analysis", tB3761);
} }
return SubscribeAck.Success(); return SubscribeAck.Success();

View File

@ -16,6 +16,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet"/> <link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet"/>
<title>后端服务</title> <title>后端服务</title>
</head> </head>
<body> <body>

View File

@ -84,7 +84,7 @@
"SaslPassword": "lixiao1980", "SaslPassword": "lixiao1980",
"KafkaReplicationFactor": 3, "KafkaReplicationFactor": 3,
"NumPartitions": 30, "NumPartitions": 30,
"ServerTagName": "JiSheCollectBus4", "ServerTagName": "JiSheCollectBus99",
"FirstCollectionTime": "2025-04-22 16:07:00" "FirstCollectionTime": "2025-04-22 16:07:00"
}, },
"IoTDBOptions": { "IoTDBOptions": {