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

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