终端一体化运控平台
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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