终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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