| #region << 版 本 注 释 >> | 
| /*---------------------------------------------------------------- | 
|  * 命名空间:WIDESEAWCS_QuartzJob.DeviceBase | 
|  * 创建者:胡童庆 | 
|  * 创建时间:2024/8/2 16:13:36 | 
|  * 版本:V1.0.0 | 
|  * 描述: | 
|  * | 
|  * ---------------------------------------------------------------- | 
|  * 修改人: | 
|  * 修改时间: | 
|  * 版本:V1.0.1 | 
|  * 修改说明: | 
|  *  | 
|  *----------------------------------------------------------------*/ | 
| #endregion << 版 本 注 释 >> | 
|   | 
| using HslCommunication; | 
| using HslCommunication.Core; | 
| using System; | 
| using System.Collections.Generic; | 
| using System.Linq; | 
| using System.Reflection; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
|   | 
| namespace WIDESEAWCS_QuartzJob.DeviceBase | 
| { | 
|     public class DeviceCommand : IDataTransfer | 
|     { | 
|         #region <Const> | 
|         #endregion <Const> | 
|   | 
|         #region <Private Member> | 
|         public ushort ReadCount { get; } | 
|   | 
|         private IByteTransform byteTransform = new ReverseBytesTransform(); | 
|         #endregion <Private Member> | 
|   | 
|         #region <Public Menber> | 
|   | 
|         #endregion <Public Menber> | 
|   | 
|         #region <Constructor function> | 
|         public DeviceCommand() | 
|         { | 
|             ushort readCount = 0; | 
|             PropertyInfo[] propertyInfos = GetType().GetProperties().Where(x => x.CanWrite).ToArray(); | 
|             foreach (PropertyInfo propertyInfo in propertyInfos) | 
|             { | 
|                 object? obj = propertyInfo.GetValue(this); | 
|                 TypeCode typeCode = Type.GetTypeCode(propertyInfo.PropertyType); | 
|                 switch (typeCode) | 
|                 { | 
|                     case TypeCode.Byte: | 
|                     case TypeCode.SByte: | 
|                     case TypeCode.Char: | 
|                         readCount += sizeof(byte); | 
|                         break; | 
|                     case TypeCode.Int16: | 
|                     case TypeCode.UInt16: | 
|                         readCount += 2; | 
|                         break; | 
|                     case TypeCode.Single: | 
|                     case TypeCode.Int32: | 
|                     case TypeCode.UInt32: | 
|                         readCount += 4; | 
|                         break; | 
|                     case TypeCode.String: | 
|                         ushort dataLength = CheckStringAttribute(propertyInfo); | 
|                         readCount += dataLength; | 
|                         break; | 
|                     default: | 
|                         throw new NotSupportedException("Unsupported primitive type: " + propertyInfo.PropertyType); | 
|                 } | 
|             } | 
|             ReadCount = readCount; | 
|         } | 
|         #endregion <Constructor function> | 
|   | 
|         #region <Private Method> | 
|         private ushort CheckStringAttribute(PropertyInfo propertyInfo) | 
|         { | 
|             Attribute? attribute = propertyInfo.GetCustomAttribute(typeof(DataLengthAttribute)); | 
|             if (attribute == null) | 
|             { | 
|                 throw new Exception($"字符串需要配置【DataLength】特性"); | 
|             } | 
|             ushort dataLength = ((DataLengthAttribute)attribute).DataLength; | 
|             if (dataLength <= 0 || dataLength > 256) | 
|             { | 
|                 throw new Exception($"【DataLength】特性请配置有效参数,参数范围【1-256】"); | 
|             } | 
|             if (dataLength % 2 != 0) | 
|             { | 
|                 dataLength += 1; | 
|             } | 
|             dataLength += 2; | 
|   | 
|             return dataLength; | 
|         } | 
|         #endregion <Private Method> | 
|   | 
|         #region <Public Method> | 
|         public void ParseSource(byte[] Content) | 
|         { | 
|             PropertyInfo[] propertyInfos = GetType().GetProperties().Where(x => x.CanWrite).ToArray(); | 
|             int index = 0; | 
|             for (int i = 0; i < propertyInfos.Length; i++) | 
|             { | 
|                 PropertyInfo propertyInfo = propertyInfos[i]; | 
|   | 
|                 TypeCode typeCode = Type.GetTypeCode(propertyInfo.PropertyType); | 
|                 switch (typeCode) | 
|                 { | 
|                     case TypeCode.Byte: | 
|                     case TypeCode.SByte: | 
|                         propertyInfo.SetValue(this, Content[index]); | 
|                         index += sizeof(byte); | 
|                         break; | 
|                     case TypeCode.Char: | 
|                         propertyInfo.SetValue(this, (char)Content[index]); | 
|                         index += sizeof(char); | 
|                         break; | 
|                     case TypeCode.Int16: | 
|                         propertyInfo.SetValue(this, byteTransform.TransInt16(Content, index)); | 
|                         index += sizeof(short); | 
|                         break; | 
|                     case TypeCode.UInt16: | 
|                         propertyInfo.SetValue(this, byteTransform.TransUInt16(Content, index)); | 
|                         index += sizeof(ushort); | 
|                         break; | 
|                     case TypeCode.Single: | 
|                         propertyInfo.SetValue(this, byteTransform.TransSingle(Content, index)); | 
|                         index += sizeof(float); | 
|                         break; | 
|                     case TypeCode.Int32: | 
|                         propertyInfo.SetValue(this, byteTransform.TransInt32(Content, index)); | 
|                         index += sizeof(int); | 
|                         break; | 
|                     case TypeCode.UInt32: | 
|                         propertyInfo.SetValue(this, byteTransform.TransUInt32(Content, index)); | 
|                         index += sizeof(uint); | 
|                         break; | 
|                     case TypeCode.String: | 
|                         ushort dataLength = CheckStringAttribute(propertyInfo); | 
|                         propertyInfo.SetValue(this, Encoding.Default.GetString(Content, index + 2, Content[index + 1])); | 
|                         index += dataLength; | 
|                         break; | 
|                     default: | 
|                         throw new NotSupportedException("Unsupported primitive type: " + propertyInfo.PropertyType); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         public byte[] ToSource() | 
|         { | 
|             int propertyValueHasNull = -1; | 
|             List<byte> bytes = new List<byte>(); | 
|             PropertyInfo[] propertyInfos = GetType().GetProperties().Where(x => x.CanWrite).ToArray(); | 
|             foreach (PropertyInfo propertyInfo in propertyInfos) | 
|             { | 
|                 object? obj = propertyInfo.GetValue(this); | 
|                 if (obj == null && propertyValueHasNull != -1) | 
|                 { | 
|                     throw new Exception($"{nameof(DeviceCommand)}错误"); | 
|                 } | 
|                 else | 
|                 { | 
|                     if (propertyValueHasNull == -1) | 
|                         propertyValueHasNull = 2; | 
|                 } | 
|                 TypeCode typeCode = Type.GetTypeCode(propertyInfo.PropertyType); | 
|                 switch (typeCode) | 
|                 { | 
|                     case TypeCode.Byte: | 
|                     case TypeCode.SByte: | 
|                     case TypeCode.Char: | 
|                         if (obj != null) | 
|                         { | 
|                             bytes.Add((byte)obj); | 
|                         } | 
|                         else | 
|                         { propertyValueHasNull = 1; } | 
|                         break; | 
|                     case TypeCode.Int16: | 
|                     case TypeCode.UInt16: | 
|                         if (obj != null) | 
|                         { | 
|                             byte[] bytesShort = BitConverter.GetBytes(Convert.ToUInt16(obj)); | 
|                             Array.Reverse(bytesShort); | 
|                             bytes.AddRange(bytesShort); | 
|                         } | 
|                         else | 
|                         { propertyValueHasNull = 1; } | 
|                         break; | 
|                     case TypeCode.Single: | 
|                         if (obj != null) | 
|                         { | 
|                             byte[] bytesSingle = BitConverter.GetBytes(Convert.ToSingle(obj)); | 
|                             Array.Reverse(bytesSingle); | 
|                             bytes.AddRange(bytesSingle); | 
|                         } | 
|                         else | 
|                         { propertyValueHasNull = 1; } | 
|                         break; | 
|                     case TypeCode.Int32: | 
|                     case TypeCode.UInt32: | 
|                         if (obj != null) | 
|                         { | 
|                             byte[] bytesInt = BitConverter.GetBytes(Convert.ToUInt32(obj)); | 
|                             Array.Reverse(bytesInt); | 
|                             bytes.AddRange(bytesInt); | 
|                         } | 
|                         else | 
|                         { propertyValueHasNull = 1; } | 
|                         break; | 
|                     case TypeCode.String: | 
|   | 
|                         if (obj != null) | 
|                         { | 
|                             ushort dataLength = CheckStringAttribute(propertyInfo); | 
|                             byte[] bytesString = Encoding.Default.GetBytes(obj.ToString()); | 
|                             bytes.Add(Convert.ToByte(dataLength)); | 
|                             bytes.Add(Convert.ToByte(obj.ToString().Length)); | 
|                             bytes.AddRange(bytesString); | 
|                             for (int i = 0; i < dataLength - obj.ToString().Length - 2; i++) | 
|                             { | 
|                                 bytes.Add(0); | 
|                             } | 
|                         } | 
|                         else | 
|                         { propertyValueHasNull = 1; } | 
|                         break; | 
|                     default: | 
|                         throw new NotSupportedException("Unsupported primitive type: " + propertyInfo.PropertyType); | 
|                 } | 
|             } | 
|   | 
|             return bytes.ToArray(); | 
|         } | 
|         #endregion <Public Method> | 
|   | 
|         #region <Event> | 
|         #endregion <Event> | 
|     } | 
| } |