终端一体化运控平台
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

427 rader
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. obj = bytes1.ToArray().ToStringb().Trim().Replace(" ", "").Replace("\n", "");
  203. numBytes += len;
  204. break;
  205. default:
  206. {
  207. object obj2 = Activator.CreateInstance(propertyType);
  208. numBytes = FromBytes(obj2, bytes, numBytes);
  209. numBytes = Math.Ceiling(numBytes);
  210. if (numBytes / 2.0 - Math.Floor(numBytes / 2.0) > 0.0)
  211. {
  212. numBytes += 1.0;
  213. }
  214. obj = obj2;
  215. break;
  216. }
  217. }
  218. return obj;
  219. }
  220. private static Encoding GetGb2312()
  221. {
  222. //获取指定的编码不存在的时候需要安装 System.Text.Encoding.CodePages nuget包
  223. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  224. return Encoding.GetEncoding("gb2312");
  225. }
  226. //public static Encoding GetGb2312(this Encoding encoding)
  227. //{
  228. // Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  229. // return Encoding.GetEncoding("gb2312");
  230. //}
  231. public static byte[] ToArrays(this string value)
  232. {
  233. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  234. return Encoding.GetEncoding("gb2312").GetBytes(value);
  235. }
  236. public static string ToStringb(this byte[] value)
  237. {
  238. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  239. return Encoding.GetEncoding("gb2312").GetString(value);
  240. }
  241. public static double FromBytes(object sourceClass, byte[] bytes, double numBytes = 0.0, bool isInnerClass = false)
  242. {
  243. if (bytes == null)
  244. {
  245. return numBytes;
  246. }
  247. foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
  248. {
  249. if (accessableProperty.PropertyType.IsArray)
  250. {
  251. Array array = (Array)accessableProperty.GetValue(sourceClass, null);
  252. IncrementToEven(ref numBytes);
  253. Type elementType = accessableProperty.PropertyType.GetElementType();
  254. for (int i = 0; i < array.Length; i++)
  255. {
  256. if (!(numBytes < (double)bytes.Length))
  257. {
  258. break;
  259. }
  260. array.SetValue(GetPropertyValue(elementType, bytes, accessableProperty, ref numBytes), i);
  261. }
  262. }
  263. else
  264. {
  265. accessableProperty.SetValue(sourceClass, GetPropertyValue(accessableProperty.PropertyType, bytes, accessableProperty, ref numBytes), null);
  266. }
  267. }
  268. return numBytes;
  269. }
  270. private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes, PropertyInfo propertyInfo)
  271. {
  272. int num = 0;
  273. int num2 = 0;
  274. byte[] array = null;
  275. switch (propertyValue.GetType().Name)
  276. {
  277. case "Boolean":
  278. num = (int)Math.Floor(numBytes);
  279. num2 = (int)((numBytes - (double)num) / 0.125);
  280. if ((bool)propertyValue)
  281. {
  282. bytes[num] |= (byte)Math.Pow(2.0, num2);
  283. }
  284. else
  285. {
  286. bytes[num] &= (byte)(~(byte)Math.Pow(2.0, num2));
  287. }
  288. numBytes += 0.125;
  289. break;
  290. case "Byte":
  291. numBytes = (int)Math.Ceiling(numBytes);
  292. num = (int)numBytes;
  293. bytes[num] = (byte)propertyValue;
  294. numBytes += 1.0;
  295. break;
  296. case "Int16":
  297. array = Int.ToByteArray((short)propertyValue);
  298. break;
  299. case "UInt16":
  300. array = Word.ToByteArray((ushort)propertyValue);
  301. break;
  302. case "Int32":
  303. array = DInt.ToByteArray((int)propertyValue);
  304. break;
  305. case "UInt32":
  306. array = DWord.ToByteArray((uint)propertyValue);
  307. break;
  308. case "Single":
  309. array = Real.ToByteArray((float)propertyValue);
  310. break;
  311. case "Double":
  312. array = LReal.ToByteArray((double)propertyValue);
  313. break;
  314. case "String":
  315. //array = new byte[256];
  316. //var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
  317. //for (int i = 0; i < res?.Length; i++) { array[i] = res[i]; }
  318. int len = 256;
  319. if (propertyInfo.CustomAttributes.Count() > 0)
  320. {
  321. var tempLen = propertyInfo.GetCustomAttribute<SiemensAttribute>();
  322. if (tempLen != null) len = tempLen.Len + 2;
  323. }
  324. array = new byte[len];
  325. //var res = GetGb2312()?.GetBytes(propertyValue?.ToString());
  326. var res = propertyValue?.ToString()?.ToArrays();
  327. if (array.Length > 2) array[0] = (byte)(len - 2); array[1] = (byte)res.Length;
  328. for (int i = 0; i < res?.Length; i++)
  329. {
  330. int index = i + 2;
  331. if (index < array.Length)
  332. array[index] = res[i];
  333. }
  334. break;
  335. default:
  336. numBytes = ToBytes(propertyValue, bytes, numBytes);
  337. //if (propertyValue.GetType().IsClass) IncrementToEven(ref numBytes);
  338. break;
  339. }
  340. if (array != null)
  341. {
  342. IncrementToEven(ref numBytes);
  343. num = (int)numBytes;
  344. for (int i = 0; i < array.Length; i++)
  345. {
  346. bytes[num + i] = array[i];
  347. }
  348. numBytes += (double)array.Length;
  349. }
  350. return numBytes;
  351. }
  352. public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0)
  353. {
  354. foreach (PropertyInfo accessableProperty in GetAccessableProperties(sourceClass.GetType()))
  355. {
  356. if (accessableProperty.PropertyType.IsArray)
  357. {
  358. Array array = (Array)accessableProperty.GetValue(sourceClass, null);
  359. IncrementToEven(ref numBytes);
  360. accessableProperty.PropertyType.GetElementType();
  361. for (int i = 0; i < array.Length; i++)
  362. {
  363. if (!(numBytes < (double)bytes.Length))
  364. {
  365. break;
  366. }
  367. numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes, accessableProperty);
  368. }
  369. }
  370. else
  371. {
  372. numBytes = SetBytesFromProperty(accessableProperty.GetValue(sourceClass, null), bytes, numBytes, accessableProperty);
  373. }
  374. }
  375. return numBytes;
  376. }
  377. private static void IncrementToEven(ref double numBytes)
  378. {
  379. numBytes = Math.Ceiling(numBytes);
  380. if (numBytes % 2.0 > 0.0)
  381. {
  382. numBytes += 1.0;
  383. }
  384. }
  385. }
  386. }