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_Communicator { public class MelsecCustomModel { #region #endregion #region public ushort ReadCount { get; } private IByteTransform byteTransform = new RegularByteTransform(); #endregion #region #endregion #region public MelsecCustomModel() { 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("不支持的基础类型: " + 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】"); } 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, byteTransform.TransString(Content.SelectMiddle(index, dataLength), Encoding.Default)); index += dataLength; break; default: throw new NotSupportedException("不支持的基础类型: " + 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($"{GetType().Name}错误"); } 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 = byteTransform.TransByte(obj.ToString(), Encoding.Default); bytes.AddRange(bytesString); } else { propertyValueHasNull = 1; } break; default: throw new NotSupportedException("不支持的基础类型: " + propertyInfo.PropertyType); } } return bytes.ToArray(); } #endregion #region #endregion } }