#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 #endregion #region public ushort ReadCount { get; } private IByteTransform byteTransform = new ReverseBytesTransform(); #endregion #region #endregion #region 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 #region 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 #region 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 bytes = new List(); 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 #region #endregion } }