|
- using Newtonsoft.Json.Linq;
- using S7.Net.Types;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Design;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace BPASmartClient.S7Net
- {
- public static class EntityClassResolution
- {
- private static IEnumerable<PropertyInfo> GetAccessableProperties(Type classType)
- {
- return from p in classType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
- where p.GetSetMethod() != null
- select p;
- }
-
- private static double GetIncreasedNumberOfBytes(double numBytes, Type type)
- {
- switch (type.Name)
- {
- case "Boolean":
- numBytes += 0.125;
- break;
- case "Byte":
- numBytes += 1.0;
- break;
- case "Int16":
- case "UInt16":
- case "Ushort":
- case "Short":
- numBytes += 2.0;
- break;
- case "Int32":
- case "UInt32":
- case "Single":
- case "float":
- numBytes += 4.0;
- break;
- case "Double":
- numBytes += 8.0;
- break;
- case "String":
- numBytes += 256.0;
- break;
- default:
- numBytes = GetClassSize(Activator.CreateInstance(type), numBytes, isInnerProperty: true);
- break;
- }
-
- return numBytes;
- }
-
- /// <summary>
- /// 获取实体类的字节大小
- /// </summary>
- /// <param name="instance"></param>
- /// <param name="numBytes"></param>
- /// <param name="isInnerProperty"></param>
- /// <returns></returns>
- /// <exception cref="Exception"></exception>
- public static double GetClassSize(object instance, double numBytes = 0.0, bool isInnerProperty = false)
- {
- foreach (PropertyInfo accessableProperty in GetAccessableProperties(instance.GetType()))
- {
- if (accessableProperty.PropertyType.IsArray)
- {
- Type elementType = accessableProperty.PropertyType.GetElementType();
- Array array = (Array)accessableProperty.GetValue(instance, null);
- if (array.Length <= 0)
- {
- throw new Exception("Cannot determine size of class, because an array is defined which has no fixed size greater than zero.");
- }
-
- IncrementToEven(ref numBytes);
- for (int i = 0; i < array.Length; i++)
- {
- numBytes = GetIncreasedNumberOfBytes(numBytes, elementType);
- }
- }
- else
- {
- numBytes = GetIncreasedNumberOfBytes(numBytes, accessableProperty.PropertyType);
- }
- }
-
- if (!isInnerProperty)
- {
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
- }
-
- return numBytes;
- }
-
- private static object? GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
- {
- object obj = null;
- switch (propertyType.Name)
- {
- case "Boolean":
- {
- int num = (int)Math.Floor(numBytes);
- int num2 = (int)((numBytes - (double)num) / 0.125);
- obj = (((bytes[num] & (int)Math.Pow(2.0, num2)) == 0) ? ((object)false) : ((object)true));
- numBytes += 0.125;
- break;
- }
- case "Byte":
- numBytes = Math.Ceiling(numBytes);
- obj = bytes[(int)numBytes];
- numBytes += 1.0;
- break;
- case "Int16":
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToShort();
- numBytes += 2.0;
- break;
- case "UInt16":
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
- numBytes += 2.0;
- break;
- case "Int32":
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = DWord.FromBytes(bytes[(int)numBytes + 3], bytes[(int)numBytes + 2], bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToInt();
- numBytes += 4.0;
- break;
- case "UInt32":
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = DWord.FromBytes(bytes[(int)numBytes], bytes[(int)numBytes + 1], bytes[(int)numBytes + 2], bytes[(int)numBytes + 3]);
- numBytes += 4.0;
- break;
- case "Single":
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = Real.FromByteArray(new byte[4]
- {
- bytes[(int)numBytes],
- bytes[(int)numBytes + 1],
- bytes[(int)numBytes + 2],
- bytes[(int)numBytes + 3]
- });
- numBytes += 4.0;
- break;
- case "Double":
- {
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- byte[] array = new byte[8];
- Array.Copy(bytes, (int)numBytes, array, 0, 8);
- obj = LReal.FromByteArray(array);
- numBytes += 8.0;
- break;
- }
- case "String":
- byte[] sarray = new byte[256];
- Array.Copy(bytes, (int)numBytes, sarray, 0, 256);
- obj = GetGb2312()?.GetString(sarray).Trim().Replace(" ", "").Replace("\n", "");
- numBytes += 256.0;
- break;
- default:
- {
- object obj2 = Activator.CreateInstance(propertyType);
- numBytes = FromBytes(obj2, bytes, numBytes);
- obj = obj2;
- break;
- }
- }
-
- return obj;
- }
-
- private static Encoding GetGb2312()
- {
- //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- return Encoding.GetEncoding("gb2312");
- }
-
- public static double FromBytes(object sourceClass, byte[] bytes, double numBytes = 0.0, bool isInnerClass = false)
- {
- if (bytes == null)
- {
- return numBytes;
- }
-
- foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
- {
- if (accessableProperty.PropertyType.IsArray)
- {
- Array array = (Array)accessableProperty.GetValue(sourceClass, null);
- IncrementToEven(ref numBytes);
- Type elementType = accessableProperty.PropertyType.GetElementType();
- for (int i = 0; i < array.Length; i++)
- {
- if (!(numBytes < (double)bytes.Length))
- {
- break;
- }
-
- array.SetValue(GetPropertyValue(elementType, bytes, ref numBytes), i);
- }
- }
- else
- {
- accessableProperty.SetValue(sourceClass, GetPropertyValue(accessableProperty.PropertyType, bytes, ref numBytes), null);
- }
- }
-
- return numBytes;
- }
-
- private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes)
- {
- int num = 0;
- int num2 = 0;
- byte[] array = null;
- switch (propertyValue.GetType().Name)
- {
- case "Boolean":
- num = (int)Math.Floor(numBytes);
- num2 = (int)((numBytes - (double)num) / 0.125);
- if ((bool)propertyValue)
- {
- bytes[num] |= (byte)Math.Pow(2.0, num2);
- }
- else
- {
- bytes[num] &= (byte)(~(byte)Math.Pow(2.0, num2));
- }
-
- numBytes += 0.125;
- break;
- case "Byte":
- numBytes = (int)Math.Ceiling(numBytes);
- num = (int)numBytes;
- bytes[num] = (byte)propertyValue;
- numBytes += 1.0;
- break;
- case "Int16":
- array = Int.ToByteArray((short)propertyValue);
- break;
- case "UInt16":
- array = Word.ToByteArray((ushort)propertyValue);
- break;
- case "Int32":
- array = DInt.ToByteArray((int)propertyValue);
- break;
- case "UInt32":
- array = DWord.ToByteArray((uint)propertyValue);
- break;
- case "Single":
- array = Real.ToByteArray((float)propertyValue);
- break;
- case "Double":
- array = LReal.ToByteArray((double)propertyValue);
- break;
- case "String":
- array = new byte[256];
- var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
- for (int i = 0; i < res?.Length; i++) { array[i] = res[i]; }
- break;
- default:
- numBytes = ToBytes(propertyValue, bytes, numBytes);
- break;
- }
-
- if (array != null)
- {
- IncrementToEven(ref numBytes);
- num = (int)numBytes;
- for (int i = 0; i < array.Length; i++)
- {
- bytes[num + i] = array[i];
- }
-
- numBytes += (double)array.Length;
- }
-
- return numBytes;
- }
-
-
- public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0)
- {
- foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
- {
- if (accessableProperty.PropertyType.IsArray)
- {
- Array array = (Array)accessableProperty.GetValue(sourceClass, null);
- IncrementToEven(ref numBytes);
- accessableProperty.PropertyType.GetElementType();
- for (int i = 0; i < array.Length; i++)
- {
- if (!(numBytes < (double)bytes.Length))
- {
- break;
- }
-
- numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes);
- }
- }
- else
- {
- numBytes = SetBytesFromProperty(accessableProperty.GetValue(sourceClass, null), bytes, numBytes);
- }
- }
-
- return numBytes;
- }
-
- private static void IncrementToEven(ref double numBytes)
- {
- numBytes = Math.Ceiling(numBytes);
- if (numBytes % 2.0 > 0.0)
- {
- numBytes += 1.0;
- }
- }
- }
- }
|