|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- 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, PropertyInfo propertyInfo)
- {
- 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;
- double len = 256.0;
- if (propertyInfo.CustomAttributes.Count() > 0)
- {
- var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
- if (tempLen != null) len = Convert.ToDouble(tempLen.Len) + 2.0;
- }
- numBytes += len;
- break;
- default:
- numBytes = GetClassSize(Activator.CreateInstance(type), numBytes, isInnerProperty: true);
- if (type.IsClass) IncrementToEven(ref numBytes);
- 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, accessableProperty);
- }
- }
- else
- {
- numBytes = GetIncreasedNumberOfBytes(numBytes, accessableProperty.PropertyType, accessableProperty);
- }
- }
-
- 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, PropertyInfo propertyInfo, 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;
-
- int len = 256;
- if (propertyInfo.CustomAttributes.Count() > 0)
- {
- var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
- if (tempLen != null) len = tempLen.Len + 2;
- }
-
- byte[] sarray = new byte[len];
- Array.Copy(bytes, (int)numBytes, sarray, 0, len);
- List<byte> bytes1 = new List<byte>();
- if (sarray.Length > 2)
- for (int i = 2; i < sarray.Length; i++) if (sarray[i] > 0) bytes1.Add(sarray[i]);
- //obj = GetGb2312()?.GetString(bytes1.ToArray()).Trim().Replace(" ", "").Replace("\n", "");
- obj = bytes1.ToArray().ToStringb().Trim().Replace(" ", "").Replace("\n", "");
- numBytes += len;
- break;
- default:
- {
- object obj2 = Activator.CreateInstance(propertyType);
- numBytes = FromBytes(obj2, bytes, numBytes);
-
- numBytes = Math.Ceiling(numBytes);
- if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
- {
- numBytes += 1.0;
- }
-
- obj = obj2;
- break;
- }
- }
-
- return obj;
- }
-
- private static Encoding GetGb2312()
- {
- //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- return Encoding.GetEncoding("gb2312");
- }
-
-
- //public static Encoding GetGb2312(this Encoding encoding)
- //{
- // Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- // return Encoding.GetEncoding("gb2312");
- //}
-
- public static byte[] ToArrays(this string value)
- {
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- return Encoding.GetEncoding("gb2312").GetBytes(value);
- }
-
- public static string ToStringb(this byte[] value)
- {
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
- return Encoding.GetEncoding("gb2312").GetString(value);
- }
-
-
- 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, accessableProperty, ref numBytes), i);
- }
- }
- else
- {
- accessableProperty.SetValue(sourceClass, GetPropertyValue(accessableProperty.PropertyType, bytes, accessableProperty, ref numBytes), null);
- }
- }
-
- return numBytes;
- }
-
- private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes, PropertyInfo propertyInfo)
- {
- 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]; }
- int len = 256;
- if (propertyInfo.CustomAttributes.Count() > 0)
- {
- var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
- if (tempLen != null) len = tempLen.Len + 2;
- }
- array = new byte[len];
- //var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
- var res = propertyValue?.ToString()?.ToArrays();
- if (array.Length > 2) array[0] = (byte)(len - 2); array[1] = (byte)res.Length;
-
- for (int i = 0; i < res?.Length; i++)
- {
- int index = i + 2;
- if (index < array.Length)
- array[index] = res[i];
- }
- break;
- default:
- numBytes = ToBytes(propertyValue, bytes, numBytes);
- //if (propertyValue.GetType().IsClass) IncrementToEven(ref 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, accessableProperty);
- }
- }
- else
- {
- numBytes = SetBytesFromProperty(accessableProperty.GetValue(sourceClass, null), bytes, numBytes, accessableProperty);
- }
- }
-
- return numBytes;
- }
-
- private static void IncrementToEven(ref double numBytes)
- {
- numBytes = Math.Ceiling(numBytes);
- if (numBytes % 2.0 > 0.0)
- {
- numBytes += 1.0;
- }
- }
- }
- }
|