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.

1004 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. private static void Invoke(Action action, bool @try = false)
  613. {
  614. if (action == null) return;
  615. if (@try)
  616. {
  617. try { action.Invoke(); } catch { }
  618. }
  619. else { action.Invoke(); }
  620. }
  621. /// <summary>在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。</summary>
  622. [MethodImpl(MethodImplOptions.NoInlining)]
  623. public static Thread InBackground(Action action, bool @try = false)
  624. {
  625. if (action == null) return null;
  626. var thread = new Thread(delegate (object v)
  627. {
  628. Invoke(() => ((Action)v)(), @try);
  629. });
  630. thread.IsBackground = true;
  631. thread.Start(action);
  632. return thread;
  633. }
  634. /// <summary>启动线程,指定 Try 将忽略 Action 抛出的异常。</summary>
  635. public static Thread StartThread(Action action, bool background = true, bool @try = false)
  636. {
  637. if (action == null) return null;
  638. var thread = new Thread(new ThreadStart(() => Invoke(action, @try)));
  639. thread.IsBackground = background;
  640. thread.Start();
  641. return thread;
  642. }
  643. #endregion
  644. #region Assembly
  645. /// <summary>列出当前域中的程序集。</summary>
  646. public static Assembly[] ListLoadedAssemblies()
  647. {
  648. return AppDomain.CurrentDomain.GetAssemblies();
  649. }
  650. /// <summary>从指定的程序集加载资源。</summary>
  651. /// <param name="name">资源的名称。</param>
  652. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  653. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  654. /// <remarks>此方法不引发异常。</remarks>
  655. public static Stream OpenResource(string name, Assembly assembly = null)
  656. {
  657. var stream = null as Stream;
  658. try
  659. {
  660. var asm = assembly ?? Assembly.GetCallingAssembly();
  661. stream = asm.GetManifestResourceStream(name);
  662. }
  663. catch { }
  664. return null;
  665. }
  666. /// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
  667. /// <param name="name">资源的名称。</param>
  668. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  669. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  670. /// <remarks>此方法不引发异常。</remarks>
  671. public static MemoryStream GetResource(string name, Assembly assembly = null)
  672. {
  673. var res = OpenResource(name, assembly);
  674. if (res == null) return null;
  675. var memory = new MemoryStream();
  676. BinaryUtility.Read(res, memory);
  677. res.Dispose();
  678. return memory;
  679. }
  680. #endregion
  681. #region Cache
  682. #if NET40
  683. /// <summary>设置缓存项。</summary>
  684. public static bool CacheSet(string key, object value, int minutes = 60)
  685. {
  686. if (TextUtility.IsEmpty(key)) return false;
  687. if (minutes < 1) return false;
  688. var policy = new CacheItemPolicy();
  689. policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes((double)NumberUtility.RestrictValue(minutes, 0, 525600));
  690. var instance = MemoryCache.Default;
  691. instance.Set(key, value, policy, null);
  692. return true;
  693. }
  694. /// <summary></summary>
  695. public static object CacheGet(string key)
  696. {
  697. if (TextUtility.IsEmpty(key)) return null;
  698. var instance = MemoryCache.Default;
  699. var entity = instance.Get(key, null);
  700. return entity;
  701. }
  702. /// <summary></summary>
  703. public static object CacheRemove(string key)
  704. {
  705. if (TextUtility.IsEmpty(key)) return null;
  706. var instance = MemoryCache.Default;
  707. var entity = instance.Remove(key, null);
  708. return entity;
  709. }
  710. #endif
  711. #endregion
  712. #region Application
  713. /// <summary>获取当前应用程序所在目录的路径。</summary>
  714. /// <remarks>
  715. /// <para>程序示例: D:\App</para>
  716. /// <para>网站示例: D:\App</para>
  717. /// </remarks>
  718. public static string ApplicationPath
  719. {
  720. get
  721. {
  722. #if NETSTD
  723. return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  724. #else
  725. return AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
  726. #endif
  727. }
  728. }
  729. /// <summary>获取数据目录的路径。</summary>
  730. public static string DataPath
  731. {
  732. get
  733. {
  734. // 检查 App_Data 目录。
  735. var appDir = ApplicationPath;
  736. var dataDir = Path.Combine(appDir, "app_data");
  737. if (StorageUtility.DirectoryExists(dataDir)) return dataDir;
  738. // 获取并创建 Data 目录。
  739. dataDir = Path.Combine(appDir, "data");
  740. if (StorageUtility.AssureDirectory(dataDir)) return dataDir;
  741. // 使用 App 目录。
  742. return appDir;
  743. }
  744. }
  745. #if NETFX || NETCORE
  746. /// <summary>获取启动目录的路径。</summary>
  747. /// <remarks>
  748. /// <para>调用: System.Windows.Forms.Application.StartupPath</para>
  749. /// <para>示例: c:\windows\system32\inetsrv</para>
  750. /// </remarks>
  751. public static string StartupPath { get => Application.StartupPath; }
  752. /// <summary>获取可执行文件的路径。</summary>
  753. /// <remarks>
  754. /// <para>调用: System.Windows.Forms.Application.ExecutablePath</para>
  755. /// <para>示例: c:\windows\system32\inetsrv\w3wp.exe</para>
  756. /// </remarks>
  757. public static string ExecutablePath { get => Application.ExecutablePath; }
  758. #endif
  759. /// <summary>
  760. /// <para>System.AppDomain.CurrentDomain.BaseDirectory</para>
  761. /// <para>D:\Website\</para>
  762. /// </summary>
  763. private static string CurrentDomainPath
  764. {
  765. get { return AppDomain.CurrentDomain.BaseDirectory; }
  766. }
  767. /// <summary>
  768. /// <para>System.IO.Directory.GetCurrentDirectory()</para>
  769. /// <para>c:\windows\system32\inetsrv</para>
  770. /// </summary>
  771. private static string CurrentDirectory
  772. {
  773. get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory
  774. }
  775. /// <summary>
  776. /// <para>System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</para>
  777. /// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
  778. /// </summary>
  779. private static string ProcessMainModule
  780. {
  781. get { return Process.GetCurrentProcess().MainModule.FileName; }
  782. }
  783. #if NETFX || NETCORE
  784. #region System.Windows.Forms.Application
  785. /// <summary>处理当前在消息队列中的所有 Windows 消息。</summary>
  786. public static void DoEvents() => Application.DoEvents();
  787. /// <summary>在没有窗体的情况下,在当前线程上开始运行标准应用程序消息循环。</summary>
  788. /// <exception cref="InvalidOperationException"></exception>
  789. public static void ApplicationRun() => Application.Run();
  790. /// <summary>在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。</summary>
  791. /// <exception cref="InvalidOperationException"></exception>
  792. public static void ApplicationRun(Form form) => Application.Run(form);
  793. /// <summary>关闭应用程序并立即启动一个新实例。</summary>
  794. public static void ApplicationRestart() => Application.Restart();
  795. /// <summary>通知所有消息泵必须终止,并且在处理了消息以后关闭所有应用程序窗口。</summary>
  796. public static void ApplicationExit() => Application.Exit();
  797. /// <summary>退出当前线程上的消息循环,并关闭该线程上的所有窗口。</summary>
  798. public static void ApplicationExitThread() => Application.ExitThread();
  799. #endregion
  800. #endif
  801. #endregion
  802. #region Debug or Test
  803. /// <summary>调用所有公共类,创建构造函数。</summary>
  804. /// <param name="assembly">要搜索类的程序集,指定为 NULL 时将获取当前程序集。</param>
  805. /// <param name="catchException">
  806. /// <para>指定为 TRUE 时将使用 TRY 语句捕获异常;</para>
  807. /// <para>指定为 FLASE 时发生异常将可能中断执行,可用于调试。</para></param>
  808. public static void InvokePublicClass(Assembly assembly = null, bool catchException = false)
  809. {
  810. const string Title = "Invoing Public Class";
  811. Console.Title = Title;
  812. var before = DateTime.Now;
  813. Logger.Internals.Info(typeof(RuntimeUtility), "Started Invoke.");
  814. var types = GetTypes(assembly ?? Assembly.GetCallingAssembly());
  815. foreach (var type in types)
  816. {
  817. if (!type.IsClass) continue;
  818. if (!type.IsPublic) continue;
  819. if (!CanNew(type)) continue;
  820. Logger.Internals.Info(typeof(RuntimeUtility), "Invoke " + type.FullName);
  821. Console.Title = type.FullName;
  822. if (catchException)
  823. {
  824. try
  825. {
  826. Activator.CreateInstance(type);
  827. }
  828. catch (Exception ex)
  829. {
  830. Logger.Internals.Exception(typeof(RuntimeUtility), ex);
  831. }
  832. }
  833. else
  834. {
  835. Activator.CreateInstance(type);
  836. }
  837. }
  838. Console.Title = Title;
  839. var after = DateTime.Now;
  840. var span = after - before;
  841. var milli = Convert.ToInt64(span.TotalMilliseconds);
  842. var duration = $"{milli / 1000D} 秒";
  843. var result = "Finished Invoke.\n\n";
  844. result += $" Duration: {duration}\n";
  845. result += $" Started: {before.ToLucid()}\n";
  846. result += $" Ended: {after.ToLucid()}\n";
  847. Logger.Internals.Info(typeof(RuntimeUtility), result);
  848. }
  849. #endregion
  850. }
  851. }