终端一体化运控平台
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

405 行
16 KiB

  1. using Newtonsoft.Json.Linq;
  2. using S7.Net.Types;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel.Design;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace BPASmartClient.S7Net
  11. {
  12. public static class EntityClassResolution
  13. {
  14. private static IEnumerable<PropertyInfo> GetAccessableProperties(Type classType)
  15. {
  16. return from p in classType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
  17. where p.GetSetMethod() != null
  18. select p;
  19. }
  20. private static double GetIncreasedNumberOfBytes(double numBytes, Type type, PropertyInfo propertyInfo)
  21. {
  22. switch (type.Name)
  23. {
  24. case "Boolean":
  25. numBytes += 0.125;
  26. break;
  27. case "Byte":
  28. numBytes += 1.0;
  29. break;
  30. case "Int16":
  31. case "UInt16":
  32. case "Ushort":
  33. case "Short":
  34. numBytes += 2.0;
  35. break;
  36. case "Int32":
  37. case "UInt32":
  38. case "Single":
  39. case "float":
  40. numBytes += 4.0;
  41. break;
  42. case "Double":
  43. numBytes += 8.0;
  44. break;
  45. case "String":
  46. //numBytes += 256.0;
  47. double len = 256.0;
  48. if (propertyInfo.CustomAttributes.Count() > 0)
  49. {
  50. var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
  51. if (tempLen != null) len = Convert.ToDouble(tempLen.Len) + 2.0;
  52. }
  53. numBytes += len;
  54. break;
  55. default:
  56. numBytes = GetClassSize(Activator.CreateInstance(type), numBytes, isInnerProperty: true);
  57. if (type.IsClass) IncrementToEven(ref numBytes);
  58. break;
  59. }
  60. return numBytes;
  61. }
  62. /// <summary>
  63. /// 获取实体类的字节大小
  64. /// </summary>
  65. /// <param name="instance"></param>
  66. /// <param name="numBytes"></param>
  67. /// <param name="isInnerProperty"></param>
  68. /// <returns></returns>
  69. /// <exception cref="Exception"></exception>
  70. public static double GetClassSize(object instance, double numBytes = 0.0, bool isInnerProperty = false)
  71. {
  72. foreach (PropertyInfo accessableProperty in GetAccessableProperties(instance.GetType()))
  73. {
  74. if (accessableProperty.PropertyType.IsArray)
  75. {
  76. Type elementType = accessableProperty.PropertyType.GetElementType();
  77. Array array = (Array)accessableProperty.GetValue(instance, null);
  78. if (array.Length <= 0)
  79. {
  80. throw new Exception("Cannot determine size of class, because an array is defined which has no fixed size greater than zero.");
  81. }
  82. IncrementToEven(ref numBytes);
  83. for (int i = 0; i < array.Length; i++)
  84. {
  85. numBytes = GetIncreasedNumberOfBytes(numBytes, elementType, accessableProperty);
  86. }
  87. }
  88. else
  89. {
  90. numBytes = GetIncreasedNumberOfBytes(numBytes, accessableProperty.PropertyType, accessableProperty);
  91. }
  92. }
  93. if (!isInnerProperty)
  94. {
  95. numBytes = Math.Ceiling(numBytes);
  96. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  97. {
  98. numBytes += 1.0;
  99. }
  100. }
  101. return numBytes;
  102. }
  103. private static object? GetPropertyValue(Type propertyType, byte[] bytes, PropertyInfo propertyInfo, ref double numBytes)
  104. {
  105. object obj = null;
  106. switch (propertyType.Name)
  107. {
  108. case "Boolean":
  109. {
  110. int num = (int)Math.Floor(numBytes);
  111. int num2 = (int)((numBytes - (double)num) / 0.125);
  112. obj = (((bytes[num] & (int)Math.Pow(2.0, num2)) == 0) ? ((object)false) : ((object)true));
  113. numBytes += 0.125;
  114. break;
  115. }
  116. case "Byte":
  117. numBytes = Math.Ceiling(numBytes);
  118. obj = bytes[(int)numBytes];
  119. numBytes += 1.0;
  120. break;
  121. case "Int16":
  122. numBytes = Math.Ceiling(numBytes);
  123. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  124. {
  125. numBytes += 1.0;
  126. }
  127. obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToShort();
  128. numBytes += 2.0;
  129. break;
  130. case "UInt16":
  131. numBytes = Math.Ceiling(numBytes);
  132. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  133. {
  134. numBytes += 1.0;
  135. }
  136. obj = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
  137. numBytes += 2.0;
  138. break;
  139. case "Int32":
  140. numBytes = Math.Ceiling(numBytes);
  141. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  142. {
  143. numBytes += 1.0;
  144. }
  145. obj = DWord.FromBytes(bytes[(int)numBytes + 3], bytes[(int)numBytes + 2], bytes[(int)numBytes + 1], bytes[(int)numBytes]).ConvertToInt();
  146. numBytes += 4.0;
  147. break;
  148. case "UInt32":
  149. numBytes = Math.Ceiling(numBytes);
  150. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  151. {
  152. numBytes += 1.0;
  153. }
  154. obj = DWord.FromBytes(bytes[(int)numBytes], bytes[(int)numBytes + 1], bytes[(int)numBytes + 2], bytes[(int)numBytes + 3]);
  155. numBytes += 4.0;
  156. break;
  157. case "Single":
  158. numBytes = Math.Ceiling(numBytes);
  159. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  160. {
  161. numBytes += 1.0;
  162. }
  163. obj = Real.FromByteArray(new byte[4]
  164. {
  165. bytes[(int)numBytes],
  166. bytes[(int)numBytes + 1],
  167. bytes[(int)numBytes + 2],
  168. bytes[(int)numBytes + 3]
  169. });
  170. numBytes += 4.0;
  171. break;
  172. case "Double":
  173. {
  174. numBytes = Math.Ceiling(numBytes);
  175. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  176. {
  177. numBytes += 1.0;
  178. }
  179. byte[] array = new byte[8];
  180. Array.Copy(bytes, (int)numBytes, array, 0, 8);
  181. obj = LReal.FromByteArray(array);
  182. numBytes += 8.0;
  183. break;
  184. }
  185. case "String":
  186. //byte[] sarray = new byte[256];
  187. //Array.Copy(bytes, (int)numBytes, sarray, 0, 256);
  188. //obj = GetGb2312()?.GetString(sarray).Trim().Replace(" ", "").Replace("\n", "");
  189. //numBytes += 256.0;
  190. int len = 256;
  191. if (propertyInfo.CustomAttributes.Count() > 0)
  192. {
  193. var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
  194. if (tempLen != null) len = tempLen.Len + 2;
  195. }
  196. byte[] sarray = new byte[len];
  197. Array.Copy(bytes, (int)numBytes, sarray, 0, len);
  198. List<byte> bytes1 = new List<byte>();
  199. if (sarray.Length > 2)
  200. for (int i = 2; i < sarray.Length; i++) if (sarray[i] > 0) bytes1.Add(sarray[i]);
  201. obj = GetGb2312()?.GetString(bytes1.ToArray()).Trim().Replace(" ", "").Replace("\n", "");
  202. numBytes += len;
  203. break;
  204. default:
  205. {
  206. object obj2 = Activator.CreateInstance(propertyType);
  207. numBytes = FromBytes(obj2, bytes, numBytes);
  208. numBytes = Math.Ceiling(numBytes);
  209. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  210. {
  211. numBytes += 1.0;
  212. }
  213. obj = obj2;
  214. break;
  215. }
  216. }
  217. return obj;
  218. }
  219. private static Encoding GetGb2312()
  220. {
  221. //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
  222. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  223. return Encoding.GetEncoding("gb2312");
  224. }
  225. public static double FromBytes(object sourceClass, byte[] bytes, double numBytes = 0.0, bool isInnerClass = false)
  226. {
  227. if (bytes == null)
  228. {
  229. return numBytes;
  230. }
  231. foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
  232. {
  233. if (accessableProperty.PropertyType.IsArray)
  234. {
  235. Array array = (Array)accessableProperty.GetValue(sourceClass, null);
  236. IncrementToEven(ref numBytes);
  237. Type elementType = accessableProperty.PropertyType.GetElementType();
  238. for (int i = 0; i < array.Length; i++)
  239. {
  240. if (!(numBytes < (double)bytes.Length))
  241. {
  242. break;
  243. }
  244. array.SetValue(GetPropertyValue(elementType, bytes, accessableProperty, ref numBytes), i);
  245. }
  246. }
  247. else
  248. {
  249. accessableProperty.SetValue(sourceClass, GetPropertyValue(accessableProperty.PropertyType, bytes, accessableProperty, ref numBytes), null);
  250. }
  251. }
  252. return numBytes;
  253. }
  254. private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes, PropertyInfo propertyInfo)
  255. {
  256. int num = 0;
  257. int num2 = 0;
  258. byte[] array = null;
  259. switch (propertyValue.GetType().Name)
  260. {
  261. case "Boolean":
  262. num = (int)Math.Floor(numBytes);
  263. num2 = (int)((numBytes - (double)num) / 0.125);
  264. if ((bool)propertyValue)
  265. {
  266. bytes[num] |= (byte)Math.Pow(2.0, num2);
  267. }
  268. else
  269. {
  270. bytes[num] &= (byte)(~(byte)Math.Pow(2.0, num2));
  271. }
  272. numBytes += 0.125;
  273. break;
  274. case "Byte":
  275. numBytes = (int)Math.Ceiling(numBytes);
  276. num = (int)numBytes;
  277. bytes[num] = (byte)propertyValue;
  278. numBytes += 1.0;
  279. break;
  280. case "Int16":
  281. array = Int.ToByteArray((short)propertyValue);
  282. break;
  283. case "UInt16":
  284. array = Word.ToByteArray((ushort)propertyValue);
  285. break;
  286. case "Int32":
  287. array = DInt.ToByteArray((int)propertyValue);
  288. break;
  289. case "UInt32":
  290. array = DWord.ToByteArray((uint)propertyValue);
  291. break;
  292. case "Single":
  293. array = Real.ToByteArray((float)propertyValue);
  294. break;
  295. case "Double":
  296. array = LReal.ToByteArray((double)propertyValue);
  297. break;
  298. case "String":
  299. //array = new byte[256];
  300. //var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
  301. //for (int i = 0; i < res?.Length; i++) { array[i] = res[i]; }
  302. int len = 256;
  303. if (propertyInfo.CustomAttributes.Count() > 0)
  304. {
  305. var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
  306. if (tempLen != null) len = tempLen.Len + 2;
  307. }
  308. array = new byte[len];
  309. var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
  310. if (array.Length > 2) array[0] = (byte)(len - 2); array[1] = (byte)res.Length;
  311. for (int i = 0; i < res?.Length; i++)
  312. {
  313. int index = i + 2;
  314. if (index < array.Length)
  315. array[index] = res[i];
  316. }
  317. break;
  318. default:
  319. numBytes = ToBytes(propertyValue, bytes, numBytes);
  320. //if (propertyValue.GetType().IsClass) IncrementToEven(ref numBytes);
  321. break;
  322. }
  323. if (array != null)
  324. {
  325. IncrementToEven(ref numBytes);
  326. num = (int)numBytes;
  327. for (int i = 0; i < array.Length; i++)
  328. {
  329. bytes[num + i] = array[i];
  330. }
  331. numBytes += (double)array.Length;
  332. }
  333. return numBytes;
  334. }
  335. public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0)
  336. {
  337. foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
  338. {
  339. if (accessableProperty.PropertyType.IsArray)
  340. {
  341. Array array = (Array)accessableProperty.GetValue(sourceClass, null);
  342. IncrementToEven(ref numBytes);
  343. accessableProperty.PropertyType.GetElementType();
  344. for (int i = 0; i < array.Length; i++)
  345. {
  346. if (!(numBytes < (double)bytes.Length))
  347. {
  348. break;
  349. }
  350. numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes, accessableProperty);
  351. }
  352. }
  353. else
  354. {
  355. numBytes = SetBytesFromProperty(accessableProperty.GetValue(sourceClass, null), bytes, numBytes, accessableProperty);
  356. }
  357. }
  358. return numBytes;
  359. }
  360. private static void IncrementToEven(ref double numBytes)
  361. {
  362. numBytes = Math.Ceiling(numBytes);
  363. if (numBytes % 2.0 > 0.0)
  364. {
  365. numBytes += 1.0;
  366. }
  367. }
  368. }
  369. }