终端一体化运控平台
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.
 
 
 

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