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.

612 lines
21 KiB

  1. using Apewer;
  2. using Apewer.Internals.QrCode;
  3. using Apewer.Models;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Reflection;
  7. using System.Text;
  8. namespace Apewer
  9. {
  10. /// <summary>类实用工具。</summary>
  11. public class ClassUtility
  12. {
  13. /// <summary>从外部加载对象。</summary>
  14. public static object CreateObject(string path, string type, bool ignoreCase)
  15. {
  16. try
  17. {
  18. var a = Assembly.LoadFrom(path);
  19. var t = a.GetType(type, false, ignoreCase);
  20. if (t != null)
  21. {
  22. var result = Activator.CreateInstance(t);
  23. return result;
  24. }
  25. }
  26. catch { }
  27. return null;
  28. }
  29. /// <summary>解析源对象。</summary>
  30. public static Dictionary<string, string> GetOrigin(TextSet instance)
  31. {
  32. if (instance == null) return null;
  33. return instance.Origin;
  34. }
  35. /// <summary>解析源对象。</summary>
  36. public static Dictionary<string, object> GetOrigin(ObjectSet instance)
  37. {
  38. if (instance == null) return null;
  39. return instance.Origin;
  40. }
  41. /// <summary>解析源对象。</summary>
  42. public static Dictionary<string, T> GetOrigin<T>(ObjectSet<T> instance) // where T : ObjectSet<T>
  43. {
  44. if (instance == null) return null;
  45. return instance.Origin;
  46. }
  47. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  48. public static T GetAttribute<T>(object target) where T : Attribute
  49. {
  50. if (target == null) return null;
  51. try { return GetAttribute<T>(target.GetType()); } catch { return null; }
  52. }
  53. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  54. public static T GetAttribute<T>(Type target, bool inherit = false) where T : Attribute
  55. {
  56. if (target == null) return null;
  57. try
  58. {
  59. var type = target;
  60. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  61. if (attributes.LongLength > 0L)
  62. {
  63. var attribute = attributes[0] as T;
  64. return attribute;
  65. }
  66. }
  67. catch { }
  68. return null;
  69. }
  70. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  71. public static T GetAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  72. {
  73. if (property == null) return null;
  74. try
  75. {
  76. var type = property;
  77. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  78. if (attributes.LongLength > 0L)
  79. {
  80. var attribute = attributes[0] as T;
  81. return attribute;
  82. }
  83. }
  84. catch { }
  85. return null;
  86. }
  87. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  88. public static T GetAttribute<T>(MethodInfo methods, bool inherit = false) where T : Attribute
  89. {
  90. if (methods == null) return null;
  91. try
  92. {
  93. var type = methods;
  94. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  95. if (attributes.LongLength > 0L)
  96. {
  97. var attribute = attributes[0] as T;
  98. return attribute;
  99. }
  100. }
  101. catch { }
  102. return null;
  103. }
  104. /// <summary>获取一个值,指示该属性是否 static。</summary>
  105. public static bool IsStatic(PropertyInfo property, bool withNonPublic = false)
  106. {
  107. if (property == null) return false;
  108. var getter = property.GetGetMethod();
  109. if (getter != null) return getter.IsStatic;
  110. if (withNonPublic)
  111. {
  112. getter = property.GetGetMethod(true);
  113. if (getter != null) return getter.IsStatic;
  114. }
  115. var setter = property.GetSetMethod();
  116. if (setter != null) return setter.IsStatic;
  117. if (withNonPublic)
  118. {
  119. setter = property.GetSetMethod(true);
  120. if (setter != null) return setter.IsStatic;
  121. }
  122. return false;
  123. }
  124. /// <summary>调用泛型对象的 ToString() 方法。</summary>
  125. public static string ToString<T>(T target)
  126. {
  127. var type = typeof(T);
  128. var methods = type.GetMethods();
  129. foreach (var method in methods)
  130. {
  131. if (method.Name != "ToString") continue;
  132. if (method.GetParameters().LongLength > 0L) continue;
  133. var result = (string)method.Invoke(target, null);
  134. return result;
  135. }
  136. return null;
  137. }
  138. /// <summary>调用方法。</summary>
  139. /// <exception cref="ArgumentException"></exception>
  140. /// <exception cref="InvalidOperationException"></exception>
  141. /// <exception cref="MethodAccessException"></exception>
  142. /// <exception cref="NotSupportedException"></exception>
  143. /// <exception cref="TargetException"></exception>
  144. /// <exception cref="TargetInvocationException"></exception>
  145. /// <exception cref="TargetParameterCountException"></exception>
  146. public static object InvokeMethod(object instance, MethodInfo method, params object[] parameters)
  147. {
  148. if (instance == null || method == null) return null;
  149. {
  150. var pis = method.GetParameters();
  151. if (pis == null || pis.Length < 1)
  152. {
  153. return method.Invoke(instance, null);
  154. }
  155. }
  156. {
  157. if (parameters == null) return method.Invoke(instance, new object[] { null });
  158. return method.Invoke(instance, parameters);
  159. }
  160. }
  161. /// <summary>获取属性值。</summary>
  162. /// <exception cref="ArgumentException"></exception>
  163. /// <exception cref="InvalidOperationException"></exception>
  164. /// <exception cref="MethodAccessException"></exception>
  165. /// <exception cref="NotSupportedException"></exception>
  166. /// <exception cref="TargetException"></exception>
  167. /// <exception cref="TargetInvocationException"></exception>
  168. /// <exception cref="TargetParameterCountException"></exception>
  169. public static T InvokeGet<T>(object instance, PropertyInfo property)
  170. {
  171. if (instance == null || property == null || !property.CanRead) return default;
  172. #if NET20 || NET40
  173. var getter = property.GetGetMethod();
  174. if (getter != null)
  175. {
  176. try
  177. {
  178. var value = getter.Invoke(instance, null);
  179. if (value != null)
  180. {
  181. return (T)value;
  182. }
  183. }
  184. catch { }
  185. }
  186. return default;
  187. #else
  188. var value = property.GetValue(instance);
  189. try { return (T)value; } catch { return default; }
  190. #endif
  191. }
  192. /// <summary>设置属性值。</summary>
  193. /// <exception cref="ArgumentException"></exception>
  194. /// <exception cref="InvalidOperationException"></exception>
  195. /// <exception cref="MethodAccessException"></exception>
  196. /// <exception cref="NotSupportedException"></exception>
  197. /// <exception cref="TargetException"></exception>
  198. /// <exception cref="TargetInvocationException"></exception>
  199. /// <exception cref="TargetParameterCountException"></exception>
  200. public static void InvokeSet<T>(object instance, PropertyInfo property, T value)
  201. {
  202. if (instance == null || property == null || !property.CanWrite) return;
  203. #if NET20 || NET40
  204. var setter = property.GetSetMethod();
  205. if (setter != null)
  206. {
  207. try {
  208. setter.Invoke(instance, new object[] { value });
  209. }
  210. catch { }
  211. }
  212. #else
  213. property.SetValue(instance, value);
  214. #endif
  215. }
  216. /// <summary>指示方法是否存在于指定类型中。</summary>
  217. public static bool ExistIn(MethodInfo method, Type type)
  218. {
  219. if (method == null) return false;
  220. if (type == null) return false;
  221. return type.Equals(method.DeclaringType.Equals(type));
  222. }
  223. /// <summary>指示方法是否存在于指定类型中。</summary>
  224. public static bool ExistIn<T>(MethodInfo method)
  225. {
  226. if (method == null) return false;
  227. var type = typeof(T);
  228. return type.Equals(method.DeclaringType.Equals(type));
  229. }
  230. /// <summary>判断指定类型可序列化。</summary>
  231. public static bool CanSerialize(Type type, bool inherit = false)
  232. {
  233. if (type == null) return false;
  234. var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit);
  235. if (nsas != null && nsas.Length > 0) return false;
  236. var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
  237. if (sas == null || sas.Length < 1) return false;
  238. return true;
  239. }
  240. /// <summary>判断指定类型具有特性。</summary>
  241. private static bool ContainsAttribute<T>(object[] attributes) where T : Attribute
  242. {
  243. if (attributes == null) return false;
  244. if (attributes.Length < 1) return false;
  245. return true;
  246. }
  247. /// <summary>判断指定类型具有特性。</summary>
  248. public static bool ContainsAttribute<T>(Type type, bool inherit = false) where T : Attribute
  249. {
  250. return type == null ? false : ContainsAttribute<T>(type.GetCustomAttributes(typeof(T), inherit));
  251. }
  252. /// <summary>判断指定属性具有特性。</summary>
  253. public static bool ContainsAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  254. {
  255. return property == null ? false : ContainsAttribute<T>(property.GetCustomAttributes(typeof(T), inherit));
  256. }
  257. /// <summary>判断基类。</summary>
  258. public static bool IsInherits(Type child, Type @base)
  259. {
  260. // 检查参数。
  261. if (child == null || @base == null) return false;
  262. // 忽略 System.Object。
  263. var quantum = typeof(object);
  264. if (@base.Equals(quantum)) return true;
  265. if (child.Equals(quantum)) return true;
  266. // 循环判断基类。
  267. var current = child;
  268. while (true)
  269. {
  270. var parent = current.BaseType;
  271. if (parent.Equals(@base)) return true;
  272. if (parent.Equals(quantum)) break;
  273. current = parent;
  274. }
  275. return false;
  276. }
  277. /// <summary></summary>
  278. public static IEnumerable<Type> GetTypes(Assembly assembly)
  279. {
  280. if (assembly == null) return null;
  281. var types = null as IEnumerable<Type>;
  282. if (types == null)
  283. {
  284. try { types = assembly.GetExportedTypes(); }
  285. catch { types = null; }
  286. }
  287. if (types == null)
  288. {
  289. try { types = assembly.GetTypes(); }
  290. catch { types = null; }
  291. }
  292. return types;
  293. }
  294. /// <summary>能从外部创建对象实例。</summary>
  295. public static bool CanNewClass<T>()
  296. {
  297. return CanNewClass(typeof(T));
  298. }
  299. /// <summary>能从外部创建对象实例。</summary>
  300. public static bool CanNewClass(Type type)
  301. {
  302. if (type == null) return false;
  303. if (!type.IsClass) return false;
  304. if (type.IsAbstract) return false;
  305. var methods = type.GetMethods();
  306. var constructors = type.GetConstructors();
  307. foreach (var i in constructors)
  308. {
  309. if (i.IsPublic)
  310. {
  311. var parameters = i.GetParameters();
  312. if (parameters.Length < 1)
  313. {
  314. return true;
  315. }
  316. }
  317. }
  318. return false;
  319. }
  320. /// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>
  321. public static T Clone<T>(T current, T failed = default(T), bool properties = true, bool fields = false) where T : new()
  322. {
  323. if (current == null) return default(T);
  324. var type = typeof(T);
  325. var target = new T();
  326. foreach (var property in type.GetProperties())
  327. {
  328. var getter = property.GetGetMethod();
  329. var setter = property.GetSetMethod();
  330. if (getter == null || setter == null) continue;
  331. var value = getter.Invoke(current, null);
  332. setter.Invoke(target, new object[] { value });
  333. }
  334. foreach (var field in type.GetFields())
  335. {
  336. var value = field.GetValue(current);
  337. field.SetValue(target, value);
  338. }
  339. return target;
  340. }
  341. /// <summary>对每个属性执行动作。</summary>
  342. public static void ForEachProperties(object instance, Action<Property> action, bool withNonPublic = true, bool withStatic = false)
  343. {
  344. if (instance == null || action == null) return;
  345. var type = instance.GetType();
  346. if (type == null) return;
  347. var properties = new List<PropertyInfo>();
  348. properties.AddRange(type.GetProperties());
  349. if (withNonPublic) properties.AddRange(type.GetProperties(BindingFlags.NonPublic));
  350. foreach (var info in properties)
  351. {
  352. var arg = new Property()
  353. {
  354. Instance = instance,
  355. Type = type,
  356. Information = info,
  357. Getter = info.GetGetMethod(),
  358. Setter = info.GetSetMethod()
  359. };
  360. if (arg.IsStatic && !withStatic) continue;
  361. action.Invoke(arg);
  362. }
  363. }
  364. /// <summary>遍历属性。</summary>
  365. public static void ForEachPublicProperties(object instance, Action<PropertyInfo> action)
  366. {
  367. if (instance != null && action != null) ForEachPublicProperties(instance.GetType(), action);
  368. }
  369. /// <summary>遍历属性。</summary>
  370. public static void ForEachPublicProperties(Type type, Action<PropertyInfo> action)
  371. {
  372. if (type == null || action == null) return;
  373. foreach (var property in type.GetProperties()) action.Invoke(property);
  374. }
  375. /// <summary>检查类型。</summary>
  376. public static bool TypeEquals(object instance, Type type)
  377. {
  378. if (instance == null) return type == null ? true : false;
  379. if (instance is PropertyInfo)
  380. {
  381. return ((PropertyInfo)instance).PropertyType.Equals(type);
  382. }
  383. if (instance is MethodInfo)
  384. {
  385. return ((MethodInfo)instance).ReturnType.Equals(type);
  386. }
  387. return instance.GetType().Equals(type);
  388. }
  389. /// <summary>检查类型。</summary>
  390. public static bool TypeEquals<T>(object instance)
  391. {
  392. return TypeEquals(instance, typeof(T));
  393. }
  394. /// <summary>安全转换为 List&lt;<typeparamref name="T"/>&gt; 对象。可指定排除 NULL 值元素。</summary>
  395. /// <typeparam name="T"></typeparam>
  396. public static List<T> ToList<T>(IEnumerable<T> objects, bool excludeNull = false)
  397. {
  398. var list = new List<T>();
  399. if (objects != null)
  400. {
  401. foreach (var value in objects)
  402. {
  403. if (excludeNull && value == null) continue;
  404. list.Add(value);
  405. }
  406. }
  407. return list;
  408. }
  409. /// <summary></summary>
  410. public static bool IsEmpty<T>(IEnumerable<T> objects)
  411. {
  412. if (objects == null) return true;
  413. foreach (var i in objects) return false;
  414. return true;
  415. }
  416. /// <summary></summary>
  417. public static bool NotEmpty<T>(IEnumerable<T> objects)
  418. {
  419. if (objects == null) return false;
  420. foreach (var i in objects) return true;
  421. return false;
  422. }
  423. /// <summary>使用默认比较器判断相等。</summary>
  424. public static bool Equals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
  425. /// <summary>确定集合是否包含特定值</summary>
  426. public static bool Contains<T>(IEnumerable<T> objects, T cell)
  427. {
  428. if (objects == null) return false;
  429. // 以 Object 类型对比。
  430. // var a = (object)cell;
  431. // foreach (var i in objects)
  432. // {
  433. // var b = (object)i;
  434. // if (a == b) return true;
  435. // }
  436. // return false;
  437. // objects 实现了含有 Contains 方法的接口。
  438. if (objects is ICollection<T>) return ((ICollection<T>)objects).Contains(cell);
  439. // cell 无效。
  440. if (cell == null)
  441. {
  442. foreach (var i in objects)
  443. {
  444. if (i == null) return true;
  445. }
  446. return false;
  447. }
  448. // cell 有效,进行默认比较。
  449. var comparer = EqualityComparer<T>.Default;
  450. foreach (var i in objects)
  451. {
  452. if (comparer.Equals(i, cell)) return true;
  453. }
  454. return false;
  455. }
  456. /// <summary>获取集合中元素的数量。</summary>
  457. public static int Count<T>(IEnumerable<T> objects)
  458. {
  459. if (objects == null) return 0;
  460. // objects 实现了含有 Contains 方法的接口。
  461. if (objects is ICollection<T>) return ((ICollection<T>)objects).Count;
  462. var count = 0;
  463. foreach (var cell in objects) count++;
  464. return count;
  465. }
  466. /// <summary>对元素去重,且去除 NULL 值。</summary>
  467. public static T[] Distinct<T>(IEnumerable<T> items)
  468. {
  469. if (items == null) throw new ArgumentNullException(nameof(items));
  470. var count = Count(items);
  471. var added = 0;
  472. var array = new T[count];
  473. var comparer = EqualityComparer<T>.Default;
  474. foreach (var item in items)
  475. {
  476. if (item == null) continue;
  477. var contains = false;
  478. foreach (var i in array)
  479. {
  480. if (comparer.Equals(i, item))
  481. {
  482. contains = true;
  483. break;
  484. }
  485. }
  486. if (contains) continue;
  487. array[added] = item;
  488. added++;
  489. }
  490. if (added < count)
  491. {
  492. var temp = new T[added];
  493. Array.Copy(array, 0, temp, 0, added);
  494. array = temp;
  495. }
  496. return array;
  497. }
  498. /// <summary></summary>
  499. public static List<T> Sub<T>(IEnumerable<T> objects, long start = 0, long count = -1, Func<T> stuffer = null)
  500. {
  501. if (count == 0) return new List<T>();
  502. var hasCount = count > 0L;
  503. var output = new List<T>();
  504. if (start < 0)
  505. {
  506. for (var i = start; i < 0; i++)
  507. {
  508. output.Add(stuffer == null ? default : stuffer());
  509. if (hasCount && output.Count >= count) return output;
  510. }
  511. }
  512. if (objects != null)
  513. {
  514. var offset = 0L;
  515. foreach (var i in objects)
  516. {
  517. if (offset < start)
  518. {
  519. offset += 1L;
  520. continue;
  521. }
  522. offset += 1L;
  523. output.Add(i);
  524. if (hasCount && output.Count >= count) return output;
  525. }
  526. }
  527. while (hasCount && output.Count < count)
  528. {
  529. output.Add(stuffer == null ? default : stuffer());
  530. }
  531. return output;
  532. }
  533. }
  534. }