修正命名错误
xiyunfei authored at 2023-04-09 21:10:58
7.41 KiB
NewLife.JT808
using System.Collections.Concurrent;
using System.Reflection;
using NewLife.Data;
using NewLife.JT808.Protocols;
using NewLife.Reflection;
using NewLife.Data;
using NewLife.Serialization;

namespace NewLife.JT808.Protocols
{
    /// <summary>消息工厂</summary>
    public class MessageFactory
    {
        #region 静态
        /// <summary>静态实例</summary>
        public static MessageFactory Instance { get; set; } = new();
        #endregion

        #region 属性
        ConcurrentDictionary<MessageKinds, Type> _map1 = new();
        ConcurrentDictionary<Type, MessageKinds> _map2 = new();

        /// <summary>类型映射</summary>
        public IDictionary<MessageKinds, Type> Maps => _map1;

        /// <summary>类型映射</summary>
        public IDictionary<Type, MessageKinds> Types => _map2;
        #endregion

        #region 方法
        /// <summary>初始化,加载内部</summary>
        public void Init()
        {
            foreach (var item in GetType().Assembly.GetTypes())
            {
                //if (item.Namespace == ns)
                {
                    var att = item.GetCustomAttribute<MessageKindAttribute>();
                    if (att != null) Register(att.Kind, item);
                }
            }
        }

        /// <summary>注册新类型</summary>
        /// <param name="kind"></param>
        /// <param name="type"></param>
        public void Register(MessageKinds kind, Type type)
        {
            _map1[kind] = type;
            _map2[type] = kind;
        }

        /// <summary>注册新类型</summary>
        /// <typeparam name="T"></typeparam>
        public void Register<T>()
        {
            var type = typeof(T);
            var att = type.GetCustomAttribute<MessageKindAttribute>();
            if (att != null) Register(att.Kind, type);
        }

        /// <summary>从指定程序集扫描并注册所有带有[MessageKind]特性的类型</summary>
        /// <param name="assembly">要扫描的程序集</param>
        public void Register(Assembly assembly)
        {
            foreach (var type in assembly.GetTypes())
            {
                var att = type.GetCustomAttribute<MessageKindAttribute>();
                if (att != null) Register(att.Kind, type);
            }
        }

        /// <summary>注册自定义消息类型映射(可覆盖已有映射)</summary>
        /// <typeparam name="T">消息体类型</typeparam>
        public void SetMap<T>()
        {
            var type = typeof(T);
            var att = type.GetCustomAttribute<MessageKindAttribute>();
            if (att != null) _map1[att.Kind] = type;
        }

        /// <summary>注册自定义消息类型映射(可覆盖已有映射)</summary>
        /// <param name="kind">消息类型</param>
        /// <param name="type">消息体类型</param>
        public void SetMap(MessageKinds kind, Type type)
        {
            _map1[kind] = type;
            _map2[type] = kind;
        }

        /// <summary>创建指定类型的模型对象</summary>
        /// <param name="kind"></param>
        /// <returns></returns>
        public object Create(MessageKinds kind)
        {
            if (!_map1.TryGetValue(kind, out var type)) return null;

            return type.CreateInstance();
        }

        /// <summary>解析消息包,得到业务模型</summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public object Parse(JTMessage message)
        {
            var msg = Create(message.Kind);
            if (msg == null) return null;

            var pk = message.Payload as IPacket;
            if (pk != null && pk.Total > 0)
            {
                var ms = pk.GetStream();
                if (msg is IAccessor accessor)
                    accessor.Read(ms, message);
                else
                    Helper.CreateReader(ms, message).TryRead(null, ref msg);

#if DEBUG
                if (ms.Position < ms.Length) throw new Exception($"解析未完成,可用[{ms.Length}],实际[{ms.Position}]");
#endif
            }

            return msg;
        }
        #endregion

        #region 辅助
        static Array _vs;
        /// <summary>获取类型名</summary>
        /// <param name="kind"></param>
        /// <returns></returns>
        public static string GetKindName(MessageKinds kind)
        {
            if (_vs == null) _vs = Enum.GetValues(typeof(MessageKinds));

            return Array.IndexOf(_vs, kind) >= 0 ? kind + "" : ((int)kind).ToString("X4");
        }

        /// <summary>是否响应消息</summary>
        /// <param name="kind"></param>
        /// <returns></returns>
        public static bool IsReply(MessageKinds kind)
        {
            return kind switch
            {
                MessageKinds.终端通用应答 or
                MessageKinds.平台通用应答 or
                MessageKinds.终端注册应答 or
                MessageKinds.查询服务器时间应答 => true,

                MessageKinds.补传分包请求 => false,

                MessageKinds.设置终端参数 or
                MessageKinds.查询终端参数 or
                MessageKinds.终端控制 or
                MessageKinds.查询指定终端参数 => false,
                MessageKinds.查询终端参数应答 => true,

                MessageKinds.查询终端属性 => false,
                MessageKinds.查询终端属性应答 => true,

                MessageKinds.位置信息汇报 => false,
                MessageKinds.位置信息查询 => false,
                MessageKinds.位置信息查询应答 => true,

                MessageKinds.临时位置跟踪控制 => false,
                MessageKinds.人工确认报警消息 => false,
                MessageKinds.链路检测 => false,

                MessageKinds.文本信息下发 => false,
                MessageKinds.文本信息下发响应 => true,

                MessageKinds.电话回拨 => false,

                MessageKinds.车辆控制 => false,
                MessageKinds.车辆控制应答 => true,

                MessageKinds.行驶记录数据采集命令 => false,
                MessageKinds.行驶记录数据上传 => false,
                MessageKinds.行驶记录参数下传命令 => false,
                MessageKinds.电子运单上报 => false,
                MessageKinds.驾驶员上报 => false,
                MessageKinds.上报驾驶员请求 => false,
                MessageKinds.定位数据批量上传 => false,
                MessageKinds.CAN总线数据上传 => false,

                MessageKinds.多媒体事件信息上传 => false,
                MessageKinds.多媒体数据上传 => false,
                MessageKinds.多媒体数据上传应答 => true,

                MessageKinds.存储多媒体数据检索 => false,
                MessageKinds.存储多媒体数据检索应答 => true,
                MessageKinds.存储多媒体数据上传 => false,

                MessageKinds.报警附件上传 => false,
                MessageKinds.报警附件信息 => false,
                MessageKinds.文件信息上传 => false,
                MessageKinds.文件上传完成 => false,
                MessageKinds.文件上传完成应答 => true,

                MessageKinds.音视频传输请求 => false,
                MessageKinds.音视频传输控制 => false,

                _ => ((int)kind & 0xF000) == 0x8000,
            };
        }
        #endregion
    }
}