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.

1009 lines
34 KiB

  1. using Apewer.Internals;
  2. using Apewer.Models;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Reflection;
  8. using System.Runtime.CompilerServices;
  9. using System.Threading;
  10. #if NET40 || NET461
  11. using System.Runtime.Caching;
  12. #endif
  13. #if NETFX || NETCORE
  14. using System.Windows.Forms;
  15. #endif
  16. namespace Apewer
  17. {
  18. /// <summary>运行时实用工具。</summary>
  19. public class RuntimeUtility
  20. {
  21. #region 反射操作
  22. /// <summary>从外部加载对象。</summary>
  23. public static object CreateObject(string path, string type, bool ignoreCase)
  24. {
  25. try
  26. {
  27. var a = Assembly.LoadFrom(path);
  28. var t = a.GetType(type, false, ignoreCase);
  29. if (t != null)
  30. {
  31. var result = Activator.CreateInstance(t);
  32. return result;
  33. }
  34. }
  35. catch { }
  36. return null;
  37. }
  38. /// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>
  39. public static T Clone<T>(T current, T failed = default(T), bool properties = true, bool fields = false) where T : new()
  40. {
  41. if (current == null) return default(T);
  42. var type = typeof(T);
  43. var target = new T();
  44. foreach (var property in type.GetProperties())
  45. {
  46. var getter = property.GetGetMethod();
  47. var setter = property.GetSetMethod();
  48. if (getter == null || setter == null) continue;
  49. var value = getter.Invoke(current, null);
  50. setter.Invoke(target, new object[] { value });
  51. }
  52. foreach (var field in type.GetFields())
  53. {
  54. var value = field.GetValue(current);
  55. field.SetValue(target, value);
  56. }
  57. return target;
  58. }
  59. /// <summary>对每个属性执行动作。</summary>
  60. public static void ForEachProperties(object instance, Action<Property> action, bool withNonPublic = true, bool withStatic = false)
  61. {
  62. if (instance == null || action == null) return;
  63. var type = instance.GetType();
  64. if (type == null) return;
  65. var properties = new List<PropertyInfo>();
  66. properties.AddRange(type.GetProperties());
  67. if (withNonPublic) properties.AddRange(type.GetProperties(BindingFlags.NonPublic));
  68. foreach (var info in properties)
  69. {
  70. var arg = new Property()
  71. {
  72. Instance = instance,
  73. Type = type,
  74. Information = info,
  75. Getter = info.GetGetMethod(),
  76. Setter = info.GetSetMethod()
  77. };
  78. if (arg.IsStatic && !withStatic) continue;
  79. action.Invoke(arg);
  80. }
  81. }
  82. /// <summary>遍历属性。</summary>
  83. public static void ForEachPublicProperties(object instance, Action<PropertyInfo> action)
  84. {
  85. if (instance != null && action != null) ForEachPublicProperties(instance.GetType(), action);
  86. }
  87. /// <summary>遍历属性。</summary>
  88. public static void ForEachPublicProperties(Type type, Action<PropertyInfo> action)
  89. {
  90. if (type == null || action == null) return;
  91. foreach (var property in type.GetProperties()) action.Invoke(property);
  92. }
  93. #endregion
  94. #region 反射验证
  95. /// <summary>判断指定类型可序列化。</summary>
  96. public static bool CanSerialize(Type type, bool inherit = false)
  97. {
  98. if (type == null) return false;
  99. var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit);
  100. if (nsas != null && nsas.Length > 0) return false;
  101. var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
  102. if (sas != null && sas.Length > 0) return true;
  103. var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit);
  104. if (tas != null && tas.Length > 0) return true;
  105. return false;
  106. }
  107. /// <summary>检查类型。</summary>
  108. public static bool TypeEquals(object instance, Type type)
  109. {
  110. if (instance == null) return type == null ? true : false;
  111. if (instance is PropertyInfo)
  112. {
  113. return ((PropertyInfo)instance).PropertyType.Equals(type);
  114. }
  115. if (instance is MethodInfo)
  116. {
  117. return ((MethodInfo)instance).ReturnType.Equals(type);
  118. }
  119. return instance.GetType().Equals(type);
  120. }
  121. /// <summary>检查类型。</summary>
  122. public static bool TypeEquals<T>(object instance) => TypeEquals(instance, typeof(T));
  123. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  124. public static T GetAttribute<T>(object target) where T : Attribute
  125. {
  126. if (target == null) return null;
  127. try { return GetAttribute<T>(target.GetType()); } catch { return null; }
  128. }
  129. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  130. public static T GetAttribute<T>(Type target, bool inherit = false) where T : Attribute
  131. {
  132. if (target == null) return null;
  133. try
  134. {
  135. var type = target;
  136. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  137. if (attributes.LongLength > 0L)
  138. {
  139. var attribute = attributes[0] as T;
  140. return attribute;
  141. }
  142. }
  143. catch { }
  144. return null;
  145. }
  146. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  147. public static T GetAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  148. {
  149. if (property == null) return null;
  150. try
  151. {
  152. var type = property;
  153. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  154. if (attributes.LongLength > 0L)
  155. {
  156. var attribute = attributes[0] as T;
  157. return attribute;
  158. }
  159. }
  160. catch { }
  161. return null;
  162. }
  163. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  164. public static T GetAttribute<T>(MethodInfo methods, bool inherit = false) where T : Attribute
  165. {
  166. if (methods == null) return null;
  167. try
  168. {
  169. var type = methods;
  170. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  171. if (attributes.LongLength > 0L)
  172. {
  173. var attribute = attributes[0] as T;
  174. return attribute;
  175. }
  176. }
  177. catch { }
  178. return null;
  179. }
  180. /// <summary>获取一个值,指示该属性是否 static。</summary>
  181. public static bool IsStatic(PropertyInfo property, bool withNonPublic = false)
  182. {
  183. if (property == null) return false;
  184. var getter = property.GetGetMethod();
  185. if (getter != null) return getter.IsStatic;
  186. if (withNonPublic)
  187. {
  188. getter = property.GetGetMethod(true);
  189. if (getter != null) return getter.IsStatic;
  190. }
  191. var setter = property.GetSetMethod();
  192. if (setter != null) return setter.IsStatic;
  193. if (withNonPublic)
  194. {
  195. setter = property.GetSetMethod(true);
  196. if (setter != null) return setter.IsStatic;
  197. }
  198. return false;
  199. }
  200. /// <summary>调用方法。</summary>
  201. /// <exception cref="ArgumentException"></exception>
  202. /// <exception cref="InvalidOperationException"></exception>
  203. /// <exception cref="MethodAccessException"></exception>
  204. /// <exception cref="NotSupportedException"></exception>
  205. /// <exception cref="TargetException"></exception>
  206. /// <exception cref="TargetInvocationException"></exception>
  207. /// <exception cref="TargetParameterCountException"></exception>
  208. public static object InvokeMethod(object instance, MethodInfo method, params object[] parameters)
  209. {
  210. if (instance == null || method == null) return null;
  211. {
  212. var pis = method.GetParameters();
  213. if (pis == null || pis.Length < 1)
  214. {
  215. return method.Invoke(instance, null);
  216. }
  217. }
  218. {
  219. if (parameters == null) return method.Invoke(instance, new object[] { null });
  220. return method.Invoke(instance, parameters);
  221. }
  222. }
  223. /// <summary>调用泛型对象的 ToString() 方法。</summary>
  224. public static string ToString<T>(T target)
  225. {
  226. var type = typeof(T);
  227. var methods = type.GetMethods();
  228. foreach (var method in methods)
  229. {
  230. if (method.Name != "ToString") continue;
  231. if (method.GetParameters().LongLength > 0L) continue;
  232. var result = (string)method.Invoke(target, null);
  233. return result;
  234. }
  235. return null;
  236. }
  237. /// <summary>获取属性值。</summary>
  238. /// <exception cref="ArgumentException"></exception>
  239. /// <exception cref="InvalidOperationException"></exception>
  240. /// <exception cref="MethodAccessException"></exception>
  241. /// <exception cref="NotSupportedException"></exception>
  242. /// <exception cref="TargetException"></exception>
  243. /// <exception cref="TargetInvocationException"></exception>
  244. /// <exception cref="TargetParameterCountException"></exception>
  245. public static T InvokeGet<T>(object instance, PropertyInfo property)
  246. {
  247. if (instance == null || property == null || !property.CanRead) return default;
  248. #if NET20 || NET40 || NET461
  249. var getter = property.GetGetMethod();
  250. if (getter != null)
  251. {
  252. try
  253. {
  254. var value = getter.Invoke(instance, null);
  255. if (value != null)
  256. {
  257. return (T)value;
  258. }
  259. }
  260. catch { }
  261. }
  262. return default;
  263. #else
  264. var value = property.GetValue(instance);
  265. try { return (T)value; } catch { return default; }
  266. #endif
  267. }
  268. /// <summary>设置属性值。</summary>
  269. /// <exception cref="ArgumentException"></exception>
  270. /// <exception cref="InvalidOperationException"></exception>
  271. /// <exception cref="MethodAccessException"></exception>
  272. /// <exception cref="NotSupportedException"></exception>
  273. /// <exception cref="TargetException"></exception>
  274. /// <exception cref="TargetInvocationException"></exception>
  275. /// <exception cref="TargetParameterCountException"></exception>
  276. public static void InvokeSet<T>(object instance, PropertyInfo property, T value)
  277. {
  278. if (instance == null || property == null || !property.CanWrite) return;
  279. #if NET20 || NET40
  280. var setter = property.GetSetMethod();
  281. if (setter != null)
  282. {
  283. try {
  284. setter.Invoke(instance, new object[] { value });
  285. }
  286. catch { }
  287. }
  288. #else
  289. property.SetValue(instance, value);
  290. #endif
  291. } /// <summary>指示方法是否存在于指定类型中。</summary>
  292. public static bool ExistIn(MethodInfo method, Type type)
  293. {
  294. if (method == null) return false;
  295. if (type == null) return false;
  296. return type.Equals(method.DeclaringType.Equals(type));
  297. }
  298. /// <summary>指示方法是否存在于指定类型中。</summary>
  299. public static bool ExistIn<T>(MethodInfo method)
  300. {
  301. if (method == null) return false;
  302. var type = typeof(T);
  303. return type.Equals(method.DeclaringType.Equals(type));
  304. }
  305. /// <summary>判断指定类型具有特性。</summary>
  306. private static bool ContainsAttribute<T>(object[] attributes) where T : Attribute
  307. {
  308. if (attributes == null) return false;
  309. if (attributes.Length < 1) return false;
  310. return true;
  311. }
  312. /// <summary>判断指定类型具有特性。</summary>
  313. public static bool ContainsAttribute<T>(Type type, bool inherit = false) where T : Attribute
  314. {
  315. return type == null ? false : ContainsAttribute<T>(type.GetCustomAttributes(typeof(T), inherit));
  316. }
  317. /// <summary>判断指定属性具有特性。</summary>
  318. public static bool ContainsAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  319. {
  320. return property == null ? false : ContainsAttribute<T>(property.GetCustomAttributes(typeof(T), inherit));
  321. }
  322. /// <summary>判断基类。</summary>
  323. public static bool IsInherits(Type child, Type @base)
  324. {
  325. // 检查参数。
  326. if (child == null || @base == null) return false;
  327. // 忽略 System.Object。
  328. var quantum = typeof(object);
  329. if (@base.Equals(quantum)) return true;
  330. if (child.Equals(quantum)) return true;
  331. // 循环判断基类。
  332. var current = child;
  333. while (true)
  334. {
  335. var parent = current.BaseType;
  336. if (parent.Equals(@base)) return true;
  337. if (parent.Equals(quantum)) break;
  338. current = parent;
  339. }
  340. return false;
  341. }
  342. /// <summary></summary>
  343. public static IEnumerable<Type> GetTypes(Assembly assembly)
  344. {
  345. if (assembly == null) return null;
  346. var types = null as IEnumerable<Type>;
  347. if (types == null)
  348. {
  349. try { types = assembly.GetExportedTypes(); }
  350. catch { types = null; }
  351. }
  352. if (types == null)
  353. {
  354. try { types = assembly.GetTypes(); }
  355. catch { types = null; }
  356. }
  357. return types;
  358. }
  359. /// <summary>能从外部创建对象实例。</summary>
  360. public static bool CanNew<T>() => CanNew(typeof(T));
  361. /// <summary>能从外部创建对象实例。</summary>
  362. public static bool CanNew(Type type)
  363. {
  364. if (type == null) return false;
  365. if (!type.IsClass && !type.IsValueType) return false;
  366. if (type.IsAbstract) return false;
  367. var constructors = type.GetConstructors();
  368. foreach (var i in constructors)
  369. {
  370. if (i.IsPublic)
  371. {
  372. var parameters = i.GetParameters();
  373. if (parameters.Length < 1)
  374. {
  375. return true;
  376. }
  377. }
  378. }
  379. return false;
  380. }
  381. #endregion
  382. #region Class Helper
  383. /// <summary>解析源对象。</summary>
  384. public static Dictionary<string, string> GetOrigin(TextSet instance)
  385. {
  386. if (instance == null) return null;
  387. return instance.Origin;
  388. }
  389. /// <summary>解析源对象。</summary>
  390. public static Dictionary<string, object> GetOrigin(ObjectSet instance)
  391. {
  392. if (instance == null) return null;
  393. return instance.Origin;
  394. }
  395. /// <summary>解析源对象。</summary>
  396. public static Dictionary<string, T> GetOrigin<T>(ObjectSet<T> instance) // where T : ObjectSet<T>
  397. {
  398. if (instance == null) return null;
  399. return instance.Origin;
  400. }
  401. /// <summary>安全转换为 List&lt;<typeparamref name="T"/>&gt; 对象。可指定排除 NULL 值元素。</summary>
  402. /// <typeparam name="T"></typeparam>
  403. public static List<T> ToList<T>(IEnumerable<T> objects, bool excludeNull = false)
  404. {
  405. var list = new List<T>();
  406. if (objects != null)
  407. {
  408. foreach (var value in objects)
  409. {
  410. if (excludeNull && value == null) continue;
  411. list.Add(value);
  412. }
  413. }
  414. return list;
  415. }
  416. /// <summary></summary>
  417. public static bool IsEmpty<T>(IEnumerable<T> objects)
  418. {
  419. if (objects == null) return true;
  420. foreach (var i in objects) return false;
  421. return true;
  422. }
  423. /// <summary></summary>
  424. public static bool NotEmpty<T>(IEnumerable<T> objects)
  425. {
  426. if (objects == null) return false;
  427. foreach (var i in objects) return true;
  428. return false;
  429. }
  430. /// <summary>使用默认比较器判断相等。</summary>
  431. public static bool Equals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
  432. /// <summary>确定集合是否包含特定值</summary>
  433. public static bool Contains<T>(IEnumerable<T> objects, T cell)
  434. {
  435. if (objects == null) return false;
  436. // 以 Object 类型对比。
  437. // var a = (object)cell;
  438. // foreach (var i in objects)
  439. // {
  440. // var b = (object)i;
  441. // if (a == b) return true;
  442. // }
  443. // return false;
  444. // objects 实现了含有 Contains 方法的接口。
  445. if (objects is ICollection<T>) return ((ICollection<T>)objects).Contains(cell);
  446. // cell 无效。
  447. if (cell == null)
  448. {
  449. foreach (var i in objects)
  450. {
  451. if (i == null) return true;
  452. }
  453. return false;
  454. }
  455. // cell 有效,进行默认比较。
  456. var comparer = EqualityComparer<T>.Default;
  457. foreach (var i in objects)
  458. {
  459. if (comparer.Equals(i, cell)) return true;
  460. }
  461. return false;
  462. }
  463. /// <summary>获取集合中元素的数量。</summary>
  464. public static int Count<T>(IEnumerable<T> objects)
  465. {
  466. if (objects == null) return 0;
  467. // objects 实现了含有 Contains 方法的接口。
  468. if (objects is ICollection<T>) return ((ICollection<T>)objects).Count;
  469. var count = 0;
  470. foreach (var cell in objects) count++;
  471. return count;
  472. }
  473. /// <summary>对元素去重,且去除 NULL 值。</summary>
  474. public static T[] Distinct<T>(IEnumerable<T> items)
  475. {
  476. if (items == null) throw new ArgumentNullException(nameof(items));
  477. var count = Count(items);
  478. var added = 0;
  479. var array = new T[count];
  480. var comparer = EqualityComparer<T>.Default;
  481. foreach (var item in items)
  482. {
  483. if (item == null) continue;
  484. var contains = false;
  485. foreach (var i in array)
  486. {
  487. if (comparer.Equals(i, item))
  488. {
  489. contains = true;
  490. break;
  491. }
  492. }
  493. if (contains) continue;
  494. array[added] = item;
  495. added++;
  496. }
  497. if (added < count)
  498. {
  499. var temp = new T[added];
  500. Array.Copy(array, 0, temp, 0, added);
  501. array = temp;
  502. }
  503. return array;
  504. }
  505. /// <summary></summary>
  506. public static List<T> Sub<T>(IEnumerable<T> objects, long start = 0, long count = -1, Func<T> stuffer = null)
  507. {
  508. if (count == 0) return new List<T>();
  509. var hasCount = count > 0L;
  510. var output = new List<T>();
  511. if (start < 0)
  512. {
  513. for (var i = start; i < 0; i++)
  514. {
  515. output.Add(stuffer == null ? default : stuffer());
  516. if (hasCount && output.Count >= count) return output;
  517. }
  518. }
  519. if (objects != null)
  520. {
  521. var offset = 0L;
  522. foreach (var i in objects)
  523. {
  524. if (offset < start)
  525. {
  526. offset += 1L;
  527. continue;
  528. }
  529. offset += 1L;
  530. output.Add(i);
  531. if (hasCount && output.Count >= count) return output;
  532. }
  533. }
  534. while (hasCount && output.Count < count)
  535. {
  536. output.Add(stuffer == null ? default : stuffer());
  537. }
  538. return output;
  539. }
  540. #endregion
  541. #region Collect & Dispose
  542. /// <summary>强制对所有代进行即时垃圾回收。</summary>
  543. public static void Collect()
  544. {
  545. GC.Collect();
  546. }
  547. /// <summary>开始自动释放内存,默认间隔为 1000 毫秒。</summary>
  548. public static void StartAutoFree()
  549. {
  550. KernelHelper.StartFree(1000);
  551. }
  552. /// <summary>开始自动释放内存,间隔以毫秒为单位。</summary>
  553. public static void StartAutoFree(int milliseconds)
  554. {
  555. KernelHelper.StartFree(milliseconds);
  556. }
  557. /// <summary>停止自动释放内存。</summary>
  558. public static void StopAutoFree()
  559. {
  560. KernelHelper.StopFree();
  561. }
  562. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  563. /// <returns>可能出现的错误信息。</returns>
  564. public static void Dispose(object @object, bool flush = false)
  565. {
  566. if (@object == null) return;
  567. var stream = @object as Stream;
  568. if (stream != null)
  569. {
  570. if (flush)
  571. {
  572. try { stream.Flush(); } catch { }
  573. }
  574. try { stream.Close(); } catch { }
  575. }
  576. var disposable = @object as IDisposable;
  577. if (disposable != null)
  578. {
  579. try
  580. {
  581. disposable.Dispose();
  582. }
  583. catch { }
  584. }
  585. }
  586. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  587. /// <returns>可能出现的错误信息。</returns>
  588. public static void Dispose<T>(IEnumerable<T> objects, bool flush = false)
  589. {
  590. if (objects != null)
  591. {
  592. foreach (var i in objects) Dispose(i, flush);
  593. }
  594. }
  595. #endregion
  596. #region Thread
  597. /// <summary>停止线程。</summary>
  598. public static void Abort(Thread thread)
  599. {
  600. if (thread == null) return;
  601. try
  602. {
  603. if (thread.IsAlive) thread.Abort();
  604. }
  605. catch { }
  606. }
  607. /// <summary>阻塞当前线程,时长以毫秒为单位。</summary>
  608. public static void Sleep(int milliseconds)
  609. {
  610. if (milliseconds > 0) Thread.Sleep(milliseconds);
  611. }
  612. /// <summary>在后台线程中执行,指定 Try 将忽略异常。</summary>
  613. [MethodImpl(MethodImplOptions.NoInlining)]
  614. public static Thread InBackground(Action action, bool @try = false)
  615. {
  616. if (action == null) return null;
  617. Thread thread;
  618. if (@try)
  619. {
  620. thread = new Thread(delegate (object v)
  621. {
  622. try
  623. {
  624. ((Action)v)();
  625. }
  626. catch { }
  627. });
  628. }
  629. else
  630. {
  631. thread = new Thread(delegate (object v)
  632. {
  633. ((Action)v)();
  634. });
  635. }
  636. thread.IsBackground = true;
  637. thread.Start(action);
  638. return thread;
  639. }
  640. /// <summary>启动线程。</summary>
  641. public static Thread StartThread(Action action, bool background = true)
  642. {
  643. if (action == null) return null;
  644. var thread = new Thread(new ThreadStart(action));
  645. thread.IsBackground = background;
  646. thread.Start();
  647. return thread;
  648. }
  649. #endregion
  650. #region Assembly
  651. /// <summary>列出当前域中的程序集。</summary>
  652. public static Assembly[] ListLoadedAssemblies()
  653. {
  654. return AppDomain.CurrentDomain.GetAssemblies();
  655. }
  656. /// <summary>从指定的程序集加载资源。</summary>
  657. /// <param name="name">资源的名称。</param>
  658. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  659. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  660. /// <remarks>此方法不引发异常。</remarks>
  661. public static Stream OpenResource(string name, Assembly assembly = null)
  662. {
  663. var stream = null as Stream;
  664. try
  665. {
  666. var asm = assembly ?? Assembly.GetCallingAssembly();
  667. stream = asm.GetManifestResourceStream(name);
  668. }
  669. catch { }
  670. return null;
  671. }
  672. /// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
  673. /// <param name="name">资源的名称。</param>
  674. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  675. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  676. /// <remarks>此方法不引发异常。</remarks>
  677. public static MemoryStream GetResource(string name, Assembly assembly = null)
  678. {
  679. var res = OpenResource(name, assembly);
  680. if (res == null) return null;
  681. var memory = new MemoryStream();
  682. BinaryUtility.Read(res, memory);
  683. res.Dispose();
  684. return memory;
  685. }
  686. #endregion
  687. #region Cache
  688. #if NET40
  689. /// <summary>设置缓存项。</summary>
  690. public static bool CacheSet(string key, object value, int minutes = 60)
  691. {
  692. if (TextUtility.IsEmpty(key)) return false;
  693. if (minutes < 1) return false;
  694. var policy = new CacheItemPolicy();
  695. policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes((double)NumberUtility.RestrictValue(minutes, 0, 525600));
  696. var instance = MemoryCache.Default;
  697. instance.Set(key, value, policy, null);
  698. return true;
  699. }
  700. /// <summary></summary>
  701. public static object CacheGet(string key)
  702. {
  703. if (TextUtility.IsEmpty(key)) return null;
  704. var instance = MemoryCache.Default;
  705. var entity = instance.Get(key, null);
  706. return entity;
  707. }
  708. /// <summary></summary>
  709. public static object CacheRemove(string key)
  710. {
  711. if (TextUtility.IsEmpty(key)) return null;
  712. var instance = MemoryCache.Default;
  713. var entity = instance.Remove(key, null);
  714. return entity;
  715. }
  716. #endif
  717. #endregion
  718. #region Application
  719. /// <summary>获取当前应用程序所在目录的路径。</summary>
  720. /// <remarks>
  721. /// <para>程序示例: D:\App</para>
  722. /// <para>网站示例: D:\App</para>
  723. /// </remarks>
  724. public static string ApplicationPath
  725. {
  726. get
  727. {
  728. #if NETSTD
  729. return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  730. #else
  731. return AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
  732. #endif
  733. }
  734. }
  735. /// <summary>获取数据目录的路径。</summary>
  736. public static string DataPath
  737. {
  738. get
  739. {
  740. // 检查 App_Data 目录。
  741. var appDir = ApplicationPath;
  742. var dataDir = Path.Combine(appDir, "app_data");
  743. if (StorageUtility.DirectoryExists(dataDir)) return dataDir;
  744. // 获取并创建 Data 目录。
  745. dataDir = Path.Combine(appDir, "data");
  746. if (StorageUtility.AssureDirectory(dataDir)) return dataDir;
  747. // 使用 App 目录。
  748. return appDir;
  749. }
  750. }
  751. #if NETFX || NETCORE
  752. /// <summary>获取启动目录的路径。</summary>
  753. /// <remarks>
  754. /// <para>调用: System.Windows.Forms.Application.StartupPath</para>
  755. /// <para>示例: c:\windows\system32\inetsrv</para>
  756. /// </remarks>
  757. public static string StartupPath { get => Application.StartupPath; }
  758. /// <summary>获取可执行文件的路径。</summary>
  759. /// <remarks>
  760. /// <para>调用: System.Windows.Forms.Application.ExecutablePath</para>
  761. /// <para>示例: c:\windows\system32\inetsrv\w3wp.exe</para>
  762. /// </remarks>
  763. public static string ExecutablePath { get => Application.ExecutablePath; }
  764. #endif
  765. /// <summary>
  766. /// <para>System.AppDomain.CurrentDomain.BaseDirectory</para>
  767. /// <para>D:\Website\</para>
  768. /// </summary>
  769. private static string CurrentDomainPath
  770. {
  771. get { return AppDomain.CurrentDomain.BaseDirectory; }
  772. }
  773. /// <summary>
  774. /// <para>System.IO.Directory.GetCurrentDirectory()</para>
  775. /// <para>c:\windows\system32\inetsrv</para>
  776. /// </summary>
  777. private static string CurrentDirectory
  778. {
  779. get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory
  780. }
  781. /// <summary>
  782. /// <para>System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</para>
  783. /// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
  784. /// </summary>
  785. private static string ProcessMainModule
  786. {
  787. get { return Process.GetCurrentProcess().MainModule.FileName; }
  788. }
  789. #if NETFX || NETCORE
  790. #region System.Windows.Forms.Application
  791. /// <summary>处理当前在消息队列中的所有 Windows 消息。</summary>
  792. public static void DoEvents() => Application.DoEvents();
  793. /// <summary>在没有窗体的情况下,在当前线程上开始运行标准应用程序消息循环。</summary>
  794. /// <exception cref="InvalidOperationException"></exception>
  795. public static void ApplicationRun() => Application.Run();
  796. /// <summary>在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。</summary>
  797. /// <exception cref="InvalidOperationException"></exception>
  798. public static void ApplicationRun(Form form) => Application.Run(form);
  799. /// <summary>关闭应用程序并立即启动一个新实例。</summary>
  800. public static void ApplicationRestart() => Application.Restart();
  801. /// <summary>通知所有消息泵必须终止,并且在处理了消息以后关闭所有应用程序窗口。</summary>
  802. public static void ApplicationExit() => Application.Exit();
  803. /// <summary>退出当前线程上的消息循环,并关闭该线程上的所有窗口。</summary>
  804. public static void ApplicationExitThread() => Application.ExitThread();
  805. #endregion
  806. #endif
  807. #endregion
  808. #region Debug or Test
  809. /// <summary>调用所有公共类,创建构造函数。</summary>
  810. /// <param name="assembly">要搜索类的程序集,指定为 NULL 时将获取当前程序集。</param>
  811. /// <param name="catchException">
  812. /// <para>指定为 TRUE 时将使用 TRY 语句捕获异常;</para>
  813. /// <para>指定为 FLASE 时发生异常将可能中断执行,可用于调试。</para></param>
  814. public static void InvokePublicClass(Assembly assembly = null, bool catchException = false)
  815. {
  816. const string Title = "Invoing Public Class";
  817. Console.Title = Title;
  818. var before = DateTime.Now;
  819. Logger.Internals.Info(typeof(RuntimeUtility), "Started Invoke.");
  820. var types = GetTypes(assembly ?? Assembly.GetCallingAssembly());
  821. foreach (var type in types)
  822. {
  823. if (!type.IsClass) continue;
  824. if (!type.IsPublic) continue;
  825. if (!CanNew(type)) continue;
  826. Logger.Internals.Info(typeof(RuntimeUtility), "Invoke " + type.FullName);
  827. Console.Title = type.FullName;
  828. if (catchException)
  829. {
  830. try
  831. {
  832. Activator.CreateInstance(type);
  833. }
  834. catch (Exception ex)
  835. {
  836. Logger.Internals.Exception(typeof(RuntimeUtility), ex);
  837. }
  838. }
  839. else
  840. {
  841. Activator.CreateInstance(type);
  842. }
  843. }
  844. Console.Title = Title;
  845. var after = DateTime.Now;
  846. var span = after - before;
  847. var milli = Convert.ToInt64(span.TotalMilliseconds);
  848. var duration = $"{milli / 1000D} 秒";
  849. var result = "Finished Invoke.\n\n";
  850. result += $" Duration: {duration}\n";
  851. result += $" Started: {before.ToLucid()}\n";
  852. result += $" Ended: {after.ToLucid()}\n";
  853. Logger.Internals.Info(typeof(RuntimeUtility), result);
  854. }
  855. #endregion
  856. }
  857. }