VisualizationParserFactory.cs 6.68 KB
using System.Collections.Concurrent;
using System.Reflection;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Rcs.Domain.Extensions;
using Rcs.Domain.Models.VDA5050;

namespace Rcs.Infrastructure.Mqtt.ParseFactory
{
    /// <summary>
    /// 可视化解析器工厂实现
    /// </summary>
    public class VisualizationParserFactory : IVisualizationParserFactory
    {
        private readonly ILogger<VisualizationParserFactory> _logger;
        private readonly ConcurrentDictionary<string, Func<string, Visualization?>> _parsers;

        public VisualizationParserFactory(ILogger<VisualizationParserFactory> logger)
        {
            _logger = logger;
            _parsers = new ConcurrentDictionary<string, Func<string, Visualization?>>(StringComparer.OrdinalIgnoreCase);
            RegisterDefaultParsers();
        }

        public Visualization? ParseVisualization(string manufacturer, string payload)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(manufacturer))
                {
                    _logger.LogWarning("制造商为空,使用默认VDA5050可视化解析器");
                    return ParseDefaultVisualization(payload);
                }

                if (_parsers.TryGetValue(manufacturer, out var parser))
                {
                    return parser(payload);
                }
                else
                {
                    _logger.LogInformation("未找到制造商 '{Manufacturer}' 的专用解析器,使用默认VDA5050解析器", manufacturer);
                    return ParseDefaultVisualization(payload);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "解析制造商 '{Manufacturer}' 的可视化信息时发生异常", manufacturer);
                return null;
            }
        }

        public void RegisterVisualizationParser(string manufacturer, Func<string, Visualization?> parser)
        {
            if (string.IsNullOrWhiteSpace(manufacturer))
            {
                throw new ArgumentException("制造商名不能为空", nameof(manufacturer));
            }

            if (parser == null)
            {
                throw new ArgumentNullException(nameof(parser));
            }

            _parsers.AddOrUpdate(manufacturer, parser, (key, old) => parser);
        }

        public bool IsManufacturerSupported(string manufacturer)
        {
            return !string.IsNullOrWhiteSpace(manufacturer) && _parsers.ContainsKey(manufacturer);
        }

        public IEnumerable<string> GetSupportedManufacturers()
        {
            return _parsers.Keys.ToList();
        }

        private void RegisterDefaultParsers()
        {
            try
            {
                var coreAssembly = Assembly.GetAssembly(typeof(Visualization));
                if (coreAssembly == null)
                {
                    _logger.LogWarning("无法获取HaHRCS.Core.Models.VDA5050 程序集");
                    return;
                }

                var visualizationTypes = coreAssembly.GetTypes()
                    .Where(type => type.IsClass && !type.IsAbstract)
                    //.Where(type => typeof(VDA5050_Header).IsAssignableFrom(type))
                    .Where(type =>
                    {
                        var protocolInfo = type.GetCustomAttribute<ProtocolInfoAttribute>();
                        return protocolInfo != null &&
                               string.Equals(protocolInfo.Topic, nameof(Visualization), StringComparison.OrdinalIgnoreCase);
                    })
                    .ToList();

                foreach (var type in visualizationTypes)
                {
                    var protocolInfo = type.GetCustomAttribute<ProtocolInfoAttribute>();
                    if (protocolInfo != null)
                    {
                        var parser = CreateParserForType(type);
                        RegisterVisualizationParser(protocolInfo.Manufacturer, parser);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "自动注册可视化默认解析器时发生异常");
            }
        }

        private Func<string, Visualization?> CreateParserForType(Type type)
        {
            return payload =>
            {
                try
                {
                    var result = JsonSerializer.Deserialize(payload, type);
                    return result as Visualization;
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "解析 {StateType} 类型时发生错误", type.Name);
                    return null;
                }
            };
        }

        private static Visualization? ParseDefaultVisualization(string payload)
        {
            try
            {
                return JsonSerializer.Deserialize<Visualization>(payload);
            }
            catch
            {
                return null;
            }
        }

        public void RefreshParsers()
        {
            _logger.LogInformation("开始手动刷新可视化解析器");
            _parsers.Clear();
            RegisterDefaultParsers();
        }

        public Dictionary<string, string> GetRegisteredParsersInfo()
        {
            var result = new Dictionary<string, string>();
            try
            {
                var coreAssembly = Assembly.GetAssembly(typeof(Visualization));
                if (coreAssembly != null)
                {
                    var types = coreAssembly.GetTypes()
                        .Where(type => type.IsClass && !type.IsAbstract)
                        .Where(type => typeof(VDA5050_Header).IsAssignableFrom(type))
                        .Where(type =>
                        {
                            var protocolInfo = type.GetCustomAttribute<ProtocolInfoAttribute>();
                            return protocolInfo != null &&
                                   protocolInfo.Topic.Equals(nameof(Visualization), StringComparison.OrdinalIgnoreCase);
                        });

                    foreach (var type in types)
                    {
                        var protocolInfo = type.GetCustomAttribute<ProtocolInfoAttribute>();
                        if (protocolInfo != null)
                        {
                            result[protocolInfo.Manufacturer] = $"{type.Name} (v{protocolInfo.Version})";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取可视化解析器信息时发生异常");
            }
            return result;
        }
    }
}