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.

872 lines
31 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  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. using System.Collections;
  11. namespace Apewer
  12. {
  13. /// <summary>运行时实用工具。</summary>
  14. public class RuntimeUtility
  15. {
  16. /// <summary>使用默认比较器判断相等。</summary>
  17. public static bool Equals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
  18. #region 反射操作
  19. /// <summary>从外部加载对象。</summary>
  20. public static object CreateObject(string path, string type, bool ignoreCase)
  21. {
  22. try
  23. {
  24. var a = Assembly.LoadFrom(path);
  25. var t = a.GetType(type, false, ignoreCase);
  26. if (t != null)
  27. {
  28. var result = Activator.CreateInstance(t);
  29. return result;
  30. }
  31. }
  32. catch { }
  33. return null;
  34. }
  35. /// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>
  36. public static T Clone<T>(T current, T failed = default(T), bool properties = true, bool fields = false) where T : new()
  37. {
  38. if (current == null) return default(T);
  39. var type = typeof(T);
  40. var target = new T();
  41. foreach (var property in type.GetProperties())
  42. {
  43. var getter = property.GetGetMethod();
  44. var setter = property.GetSetMethod();
  45. if (getter == null || setter == null) continue;
  46. var value = getter.Invoke(current, null);
  47. setter.Invoke(target, new object[] { value });
  48. }
  49. foreach (var field in type.GetFields())
  50. {
  51. var value = field.GetValue(current);
  52. field.SetValue(target, value);
  53. }
  54. return target;
  55. }
  56. /// <summary>对每个属性执行动作。</summary>
  57. public static void ForEachProperties(object instance, Action<Property> action, bool withNonPublic = true, bool withStatic = false)
  58. {
  59. if (instance == null || action == null) return;
  60. var type = instance.GetType();
  61. if (type == null) return;
  62. var properties = new List<PropertyInfo>();
  63. properties.AddRange(type.GetProperties());
  64. if (withNonPublic) properties.AddRange(type.GetProperties(BindingFlags.NonPublic));
  65. foreach (var info in properties)
  66. {
  67. var arg = new Property()
  68. {
  69. Instance = instance,
  70. Type = type,
  71. Information = info,
  72. Getter = info.GetGetMethod(),
  73. Setter = info.GetSetMethod()
  74. };
  75. if (arg.IsStatic && !withStatic) continue;
  76. action.Invoke(arg);
  77. }
  78. }
  79. #endregion
  80. #region 反射验证
  81. /// <summary>判断指定类型可序列化。</summary>
  82. public static bool CanSerialize(Type type, bool inherit = false)
  83. {
  84. if (type == null) return false;
  85. var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit);
  86. if (nsas != null && nsas.Length > 0) return false;
  87. var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
  88. if (sas != null && sas.Length > 0) return true;
  89. var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit);
  90. if (tas != null && tas.Length > 0) return true;
  91. return false;
  92. }
  93. /// <summary>检查类型。</summary>
  94. public static bool TypeEquals(object instance, Type type)
  95. {
  96. if (instance == null) return type == null ? true : false;
  97. if (instance is PropertyInfo)
  98. {
  99. return ((PropertyInfo)instance).PropertyType.Equals(type);
  100. }
  101. if (instance is MethodInfo)
  102. {
  103. return ((MethodInfo)instance).ReturnType.Equals(type);
  104. }
  105. return instance.GetType().Equals(type);
  106. }
  107. /// <summary>检查类型。</summary>
  108. public static bool TypeEquals<T>(object instance) => TypeEquals(instance, typeof(T));
  109. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  110. public static T GetAttribute<T>(object target) where T : Attribute
  111. {
  112. if (target == null) return null;
  113. try { return GetAttribute<T>(target.GetType()); } catch { return null; }
  114. }
  115. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  116. public static T GetAttribute<T>(Type target, bool inherit = false) where T : Attribute
  117. {
  118. if (target == null) return null;
  119. try
  120. {
  121. var type = target;
  122. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  123. if (attributes.LongLength > 0L)
  124. {
  125. var attribute = attributes[0] as T;
  126. return attribute;
  127. }
  128. }
  129. catch { }
  130. return null;
  131. }
  132. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  133. public static T GetAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  134. {
  135. if (property == null) return null;
  136. try
  137. {
  138. var type = property;
  139. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  140. if (attributes.LongLength > 0L)
  141. {
  142. var attribute = attributes[0] as T;
  143. return attribute;
  144. }
  145. }
  146. catch { }
  147. return null;
  148. }
  149. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  150. public static T GetAttribute<T>(MethodInfo methods, bool inherit = false) where T : Attribute
  151. {
  152. if (methods == null) return null;
  153. try
  154. {
  155. var type = methods;
  156. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  157. if (attributes.LongLength > 0L)
  158. {
  159. var attribute = attributes[0] as T;
  160. return attribute;
  161. }
  162. }
  163. catch { }
  164. return null;
  165. }
  166. /// <summary>获取一个值,指示该属性是否 static。</summary>
  167. public static bool IsStatic(PropertyInfo property, bool withNonPublic = false)
  168. {
  169. if (property == null) return false;
  170. var getter = property.GetGetMethod();
  171. if (getter != null) return getter.IsStatic;
  172. if (withNonPublic)
  173. {
  174. getter = property.GetGetMethod(true);
  175. if (getter != null) return getter.IsStatic;
  176. }
  177. var setter = property.GetSetMethod();
  178. if (setter != null) return setter.IsStatic;
  179. if (withNonPublic)
  180. {
  181. setter = property.GetSetMethod(true);
  182. if (setter != null) return setter.IsStatic;
  183. }
  184. return false;
  185. }
  186. /// <summary>调用方法。</summary>
  187. /// <exception cref="ArgumentException"></exception>
  188. /// <exception cref="InvalidOperationException"></exception>
  189. /// <exception cref="MethodAccessException"></exception>
  190. /// <exception cref="NotSupportedException"></exception>
  191. /// <exception cref="TargetException"></exception>
  192. /// <exception cref="TargetInvocationException"></exception>
  193. /// <exception cref="TargetParameterCountException"></exception>
  194. public static object InvokeMethod(object instance, MethodInfo method, params object[] parameters)
  195. {
  196. if (instance == null || method == null) return null;
  197. {
  198. var pis = method.GetParameters();
  199. if (pis == null || pis.Length < 1)
  200. {
  201. return method.Invoke(instance, null);
  202. }
  203. }
  204. {
  205. if (parameters == null) return method.Invoke(instance, new object[] { null });
  206. return method.Invoke(instance, parameters);
  207. }
  208. }
  209. /// <summary>调用泛型对象的 ToString() 方法。</summary>
  210. public static string ToString<T>(T target)
  211. {
  212. var type = typeof(T);
  213. var methods = type.GetMethods();
  214. foreach (var method in methods)
  215. {
  216. if (method.Name != "ToString") continue;
  217. if (method.GetParameters().LongLength > 0L) continue;
  218. var result = (string)method.Invoke(target, null);
  219. return result;
  220. }
  221. return null;
  222. }
  223. /// <summary>获取属性值。</summary>
  224. /// <exception cref="ArgumentException"></exception>
  225. /// <exception cref="InvalidOperationException"></exception>
  226. /// <exception cref="MethodAccessException"></exception>
  227. /// <exception cref="NotSupportedException"></exception>
  228. /// <exception cref="TargetException"></exception>
  229. /// <exception cref="TargetInvocationException"></exception>
  230. /// <exception cref="TargetParameterCountException"></exception>
  231. public static T InvokeGet<T>(object instance, PropertyInfo property)
  232. {
  233. if (instance == null || property == null || !property.CanRead) return default;
  234. #if NET20 || NET40 || NET461
  235. var getter = property.GetGetMethod();
  236. if (getter != null)
  237. {
  238. try
  239. {
  240. var value = getter.Invoke(instance, null);
  241. if (value != null)
  242. {
  243. return (T)value;
  244. }
  245. }
  246. catch { }
  247. }
  248. return default;
  249. #else
  250. var value = property.GetValue(instance);
  251. try { return (T)value; } catch { return default; }
  252. #endif
  253. }
  254. /// <summary>设置属性值。</summary>
  255. /// <exception cref="ArgumentException"></exception>
  256. /// <exception cref="InvalidOperationException"></exception>
  257. /// <exception cref="MethodAccessException"></exception>
  258. /// <exception cref="NotSupportedException"></exception>
  259. /// <exception cref="TargetException"></exception>
  260. /// <exception cref="TargetInvocationException"></exception>
  261. /// <exception cref="TargetParameterCountException"></exception>
  262. public static void InvokeSet<T>(object instance, PropertyInfo property, T value)
  263. {
  264. if (instance == null || property == null || !property.CanWrite) return;
  265. #if NET20 || NET40
  266. var setter = property.GetSetMethod();
  267. if (setter != null)
  268. {
  269. try
  270. {
  271. setter.Invoke(instance, new object[] { value });
  272. }
  273. catch { }
  274. }
  275. #else
  276. property.SetValue(instance, value);
  277. #endif
  278. }
  279. /// <summary>指示方法是否存在于指定类型中。</summary>
  280. public static bool ExistIn(MethodInfo method, Type type)
  281. {
  282. if (method == null) return false;
  283. if (type == null) return false;
  284. return type.Equals(method.DeclaringType.Equals(type));
  285. }
  286. /// <summary>指示方法是否存在于指定类型中。</summary>
  287. public static bool ExistIn<T>(MethodInfo method)
  288. {
  289. if (method == null) return false;
  290. var type = typeof(T);
  291. return type.Equals(method.DeclaringType.Equals(type));
  292. }
  293. /// <summary>判断指定类型具有特性。</summary>
  294. private static bool Contains<T>(object[] attributes) where T : Attribute
  295. {
  296. if (attributes == null) return false;
  297. if (attributes.Length < 1) return false;
  298. return true;
  299. }
  300. /// <summary>判断指定类型具有特性。</summary>
  301. public static bool Contains<T>(ICustomAttributeProvider model, bool inherit = false) where T : Attribute
  302. {
  303. if (model == null) return false;
  304. return Contains<T>(model.GetCustomAttributes(typeof(T), inherit));
  305. }
  306. /// <summary>判断基类。</summary>
  307. public static bool IsInherits(Type child, Type @base)
  308. {
  309. // 检查参数。
  310. if (child == null || @base == null || child == @base) return false;
  311. // 忽略 System.Object。
  312. var quantum = typeof(object);
  313. if (@base.Equals(quantum)) return true;
  314. if (child.Equals(quantum)) return false;
  315. // 循环判断基类。
  316. var current = child;
  317. while (true)
  318. {
  319. var parent = current.BaseType;
  320. if (parent == null) return false;
  321. if (parent.Equals(@base)) return true;
  322. if (parent.Equals(quantum)) break;
  323. current = parent;
  324. }
  325. return false;
  326. }
  327. /// <summary></summary>
  328. public static Type[] GetTypes(Assembly assembly, bool onlyExported = false)
  329. {
  330. if (assembly == null) return null;
  331. try
  332. {
  333. return onlyExported ? assembly.GetExportedTypes() : assembly.GetTypes();
  334. }
  335. catch { }
  336. return new Type[0];
  337. }
  338. /// <summary>能从外部创建对象实例。</summary>
  339. public static bool CanNew<T>() => CanNew(typeof(T));
  340. /// <summary>能从外部创建对象实例。</summary>
  341. public static bool CanNew(Type type)
  342. {
  343. if (type == null) return false;
  344. if (!type.IsClass && !type.IsValueType) return false;
  345. if (type.IsAbstract) return false;
  346. var constructors = type.GetConstructors();
  347. foreach (var i in constructors)
  348. {
  349. if (i.IsPublic)
  350. {
  351. var parameters = i.GetParameters();
  352. if (parameters.Length < 1)
  353. {
  354. return true;
  355. }
  356. }
  357. }
  358. return false;
  359. }
  360. /// <summary>获取指定类型的默认值。</summary>
  361. public static object Default(Type type)
  362. {
  363. if (type == null || !type.IsValueType) return null;
  364. return Activator.CreateInstance(type);
  365. }
  366. /// <summary>判断指定对象是否为默认值。</summary>
  367. public static bool IsDefault(object value)
  368. {
  369. if (value == null) return true;
  370. var type = value.GetType();
  371. if (type.IsValueType) return value.Equals(Activator.CreateInstance(type));
  372. return false;
  373. }
  374. /// <summary>在程序集中枚举派生类型,可自定义检查器。</summary>
  375. public static Type[] DerivedTypes(Type baseType, Assembly assembly, Func<Type, bool> checker)
  376. {
  377. if (baseType == null) return new Type[0];
  378. if (assembly == null) return new Type[0];
  379. var types = GetTypes(assembly);
  380. var list = new List<Type>(types.Length);
  381. foreach (var type in types)
  382. {
  383. if (!IsInherits(type, baseType)) continue;
  384. if (checker != null && !checker(type)) continue;
  385. list.Add(type);
  386. }
  387. return list.ToArray();
  388. }
  389. #endregion
  390. #region Collect & Dispose
  391. /// <summary>控制系统垃圾回收器(一种自动回收未使用内存的服务)。强制对所有代进行即时垃圾回收。</summary>
  392. public static void Collect() => GC.Collect();
  393. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  394. /// <returns>可能出现的错误信息。</returns>
  395. public static void Dispose(object @object, bool flush = false)
  396. {
  397. if (@object == null) return;
  398. var stream = @object as Stream;
  399. if (stream != null)
  400. {
  401. if (flush)
  402. {
  403. try { stream.Flush(); } catch { }
  404. }
  405. try { stream.Close(); } catch { }
  406. }
  407. var disposable = @object as IDisposable;
  408. if (disposable != null)
  409. {
  410. try
  411. {
  412. disposable.Dispose();
  413. }
  414. catch { }
  415. }
  416. }
  417. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  418. /// <returns>可能出现的错误信息。</returns>
  419. public static void Dispose<T>(IEnumerable<T> objects, bool flush = false)
  420. {
  421. if (objects != null)
  422. {
  423. foreach (var i in objects) Dispose(i, flush);
  424. }
  425. }
  426. #endregion
  427. #region Thread
  428. /// <summary>停止线程。</summary>
  429. public static void Abort(Thread thread)
  430. {
  431. if (thread == null) return;
  432. try
  433. {
  434. if (thread.IsAlive) thread.Abort();
  435. }
  436. catch { }
  437. }
  438. /// <summary>阻塞当前线程,时长以毫秒为单位。</summary>
  439. public static void Sleep(int milliseconds)
  440. {
  441. if (milliseconds > 0) Thread.Sleep(milliseconds);
  442. }
  443. private static void Invoke(Action action, bool @try = false)
  444. {
  445. if (action == null) return;
  446. if (@try)
  447. {
  448. try { action.Invoke(); } catch { }
  449. }
  450. else { action.Invoke(); }
  451. }
  452. /// <summary>在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。</summary>
  453. /// <param name="action">要执行的 Action。</param>
  454. /// <param name="try">忽略 Action 抛出的异常。</param>
  455. /// <remarks>对返回的 Thread 调用 Abort 可结束线程的执行。</remarks>
  456. [MethodImpl(MethodImplOptions.NoInlining)]
  457. public static Thread InBackground(Action action, bool @try = false)
  458. {
  459. if (action == null) return null;
  460. var thread = new Thread(delegate (object v)
  461. {
  462. Invoke(() => ((Action)v)(), @try);
  463. });
  464. thread.IsBackground = true;
  465. thread.Start(action);
  466. return thread;
  467. }
  468. /// <summary>启动线程,在新线程中执行。</summary>
  469. /// <param name="action">要执行的 Action。</param>
  470. /// <param name="background">设置线程为后台线程。</param>
  471. /// <param name="try">忽略 Action 抛出的异常。</param>
  472. /// <remarks>对返回的 Thread 调用 Abort 可结束线程的执行。</remarks>
  473. public static Thread StartThread(Action action, bool background = false, bool @try = false)
  474. {
  475. if (action == null) return null;
  476. var thread = new Thread(new ThreadStart(() => Invoke(action, @try)));
  477. thread.IsBackground = background;
  478. thread.Start();
  479. return thread;
  480. }
  481. /// <summary>经过指定时间(以毫秒为单位)后,在新线程(后台)中执行。</summary>
  482. /// <param name="action">要执行的 Action。</param>
  483. /// <param name="delay">调用 Action 之前延迟的时间量(以毫秒为单位)。</param>
  484. /// <param name="try">忽略 Action 抛出的异常。</param>
  485. /// <remarks>对返回的 Timer 调用 Dispose 可终止计时器,阻止调用。</remarks>
  486. public static Timer Timeout(Action action, int delay, bool @try = false)
  487. {
  488. if (action == null) return null;
  489. return new Timer((x) => Invoke((Action)x, @try), action, delay > 0 ? delay : 0, -1);
  490. }
  491. #endregion
  492. #region Assembly
  493. /// <summary>列出当前域中的程序集。</summary>
  494. public static Assembly[] ListLoadedAssemblies()
  495. {
  496. return AppDomain.CurrentDomain.GetAssemblies();
  497. }
  498. /// <summary>从指定的程序集加载资源。</summary>
  499. /// <param name="name">资源的名称。</param>
  500. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  501. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  502. /// <remarks>此方法不引发异常。</remarks>
  503. public static Stream OpenResource(string name, Assembly assembly = null)
  504. {
  505. var stream = null as Stream;
  506. try
  507. {
  508. var asm = assembly ?? Assembly.GetCallingAssembly();
  509. stream = asm.GetManifestResourceStream(name);
  510. }
  511. catch { }
  512. return null;
  513. }
  514. /// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
  515. /// <param name="name">资源的名称。</param>
  516. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  517. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  518. /// <remarks>此方法不引发异常。</remarks>
  519. public static MemoryStream GetResource(string name, Assembly assembly = null)
  520. {
  521. var res = OpenResource(name, assembly);
  522. if (res == null) return null;
  523. var memory = new MemoryStream();
  524. BytesUtility.Read(res, memory);
  525. res.Dispose();
  526. return memory;
  527. }
  528. #endregion
  529. #region Application
  530. private static Class<string> _AppPath = null;
  531. private static Class<string> _DataPath = null;
  532. private static Class<bool> _InIIS = null;
  533. /// <summary>当前应用程序由 IIS 托管。</summary>
  534. public static bool InIIS()
  535. {
  536. if (_InIIS != null) return _InIIS.Value;
  537. var dll = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
  538. var path1 = StorageUtility.CombinePath(ApplicationPath, dll);
  539. if (!File.Exists(path1))
  540. {
  541. var path2 = StorageUtility.CombinePath(ApplicationPath, "bin", dll);
  542. if (File.Exists(path2))
  543. {
  544. _InIIS = new Class<bool>(true);
  545. return true;
  546. }
  547. }
  548. _InIIS = new Class<bool>(false);
  549. return false;
  550. }
  551. /// <summary>获取当前应用程序所在目录的路径。</summary>
  552. /// <remarks>
  553. /// <para>程序示例: D:\App</para>
  554. /// <para>网站示例: D:\Website</para>
  555. /// </remarks>
  556. public static string ApplicationPath
  557. {
  558. get
  559. {
  560. var temp = _AppPath;
  561. if (!temp)
  562. {
  563. // AppDomain.CurrentDomain.BaseDirectory
  564. // AppDomain.CurrentDomain.SetupInformation.ApplicationBase
  565. // return AppDomain.CurrentDomain.BaseDirectory;
  566. #if NETSTD
  567. var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  568. #else
  569. var path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
  570. #endif
  571. temp = new Class<string>(path);
  572. _AppPath = temp;
  573. }
  574. return temp.Value;
  575. }
  576. }
  577. /// <summary>获取数据目录的路径。</summary>
  578. public static string DataPath
  579. {
  580. get
  581. {
  582. var temp = _DataPath;
  583. if (!temp)
  584. {
  585. var app = ApplicationPath;
  586. // 网站使用 App_Data 目录。
  587. var appData = Path.Combine(app, "app_data");
  588. if (Directory.Exists(appData))
  589. {
  590. temp = new Class<string>(appData);
  591. }
  592. else if (File.Exists(Path.Combine(app, "web.config")))
  593. {
  594. StorageUtility.AssureDirectory(appData);
  595. temp = new Class<string>(appData);
  596. }
  597. else
  598. {
  599. // 获取并创建 Data 目录。
  600. var data = Path.Combine(app, "data");
  601. if (StorageUtility.AssureDirectory(data)) temp = new Class<string>(data);
  602. else temp = new Class<string>(app);
  603. }
  604. _DataPath = temp;
  605. }
  606. return temp.Value;
  607. }
  608. }
  609. /// <summary>获取可执行文件的路径。</summary>
  610. /// <remarks>
  611. /// <para>调用: System.Windows.Forms.Application.ExecutablePath</para>
  612. /// <para>示例: c:\windows\system32\inetsrv\w3wp.exe</para>
  613. /// </remarks>
  614. public static string ExecutablePath
  615. {
  616. get
  617. {
  618. var entry = Assembly.GetEntryAssembly();
  619. var escapedCodeBase = entry.EscapedCodeBase;
  620. var uri = new Uri(escapedCodeBase);
  621. if (uri.Scheme == "file") return uri.LocalPath + uri.Fragment;
  622. return uri.ToString();
  623. }
  624. }
  625. /// <summary>
  626. /// <para>System.AppDomain.CurrentDomain.BaseDirectory</para>
  627. /// <para>D:\Website\</para>
  628. /// </summary>
  629. private static string CurrentDomainPath
  630. {
  631. get { return AppDomain.CurrentDomain.BaseDirectory; }
  632. }
  633. /// <summary>
  634. /// <para>System.IO.Directory.GetCurrentDirectory()</para>
  635. /// <para>c:\windows\system32\inetsrv</para>
  636. /// </summary>
  637. private static string CurrentDirectory
  638. {
  639. get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory
  640. }
  641. /// <summary>
  642. /// <para>System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</para>
  643. /// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
  644. /// </summary>
  645. private static string ProcessMainModule
  646. {
  647. get { return Process.GetCurrentProcess().MainModule.FileName; }
  648. }
  649. #endregion
  650. #region Evaluate
  651. /// <summary>评估 Action 的执行时间,单位为毫秒。</summary>
  652. public static long Evaluate(Action action)
  653. {
  654. if (action == null) return 0;
  655. var stopwatch = new Stopwatch();
  656. stopwatch.Start();
  657. action.Invoke();
  658. stopwatch.Stop();
  659. return stopwatch.ElapsedMilliseconds;
  660. }
  661. #endregion
  662. #region Console
  663. /// <summary>获取或设置控制台标题。</summary>
  664. public static string Title
  665. {
  666. get { try { return Console.Title; } catch { return null; } }
  667. set { try { Console.Title = value; } catch { } }
  668. }
  669. /// <summary>设置在控制台中按 CTRL + C 时的方法。</summary>
  670. public static void CtrlCancel(Func<bool> exit)
  671. {
  672. const string postfix = " - 按 CTRL + C 可安全退出";
  673. var title = Title ?? "";
  674. if (!title.EndsWith(postfix))
  675. {
  676. title = title + postfix;
  677. Title = title;
  678. }
  679. if (exit == null) return;
  680. try { Console.CancelKeyPress += (s, e) => e.Cancel = !exit(); } catch { }
  681. }
  682. /// <summary>调用所有公共类,创建构造函数。</summary>
  683. /// <param name="assembly">要搜索类的程序集,指定为 NULL 时将获取当前程序集。</param>
  684. /// <param name="catchException">
  685. /// <para>指定为 TRUE 时将使用 TRY 语句捕获异常;</para>
  686. /// <para>指定为 FLASE 时发生异常将可能中断执行,可用于调试。</para></param>
  687. public static void InvokePublicClass(Assembly assembly = null, bool catchException = false)
  688. {
  689. const string Title = "Invoing Public Class";
  690. RuntimeUtility.Title = Title;
  691. var before = DateTime.Now;
  692. Logger.Internals.Info(typeof(RuntimeUtility), "Started Invoke.");
  693. var types = GetTypes(assembly ?? Assembly.GetCallingAssembly());
  694. foreach (var type in types)
  695. {
  696. if (!type.IsClass) continue;
  697. if (!type.IsPublic) continue;
  698. if (!CanNew(type)) continue;
  699. Logger.Internals.Info(typeof(RuntimeUtility), "Invoke " + type.FullName);
  700. RuntimeUtility.Title = type.FullName;
  701. if (catchException)
  702. {
  703. try
  704. {
  705. Activator.CreateInstance(type);
  706. }
  707. catch (Exception ex)
  708. {
  709. Logger.Internals.Exception(typeof(RuntimeUtility), ex);
  710. }
  711. }
  712. else
  713. {
  714. Activator.CreateInstance(type);
  715. }
  716. }
  717. RuntimeUtility.Title = Title;
  718. var after = DateTime.Now;
  719. var span = after - before;
  720. var milli = Convert.ToInt64(span.TotalMilliseconds);
  721. var duration = $"{milli / 1000D} 秒";
  722. var result = "Finished Invoke.\n\n";
  723. result += $" Duration: {duration}\n";
  724. result += $" Started: {before.Lucid()}\n";
  725. result += $" Ended: {after.Lucid()}\n";
  726. Logger.Internals.Info(typeof(RuntimeUtility), result);
  727. }
  728. #endregion
  729. #region System
  730. #if NETSTD || NETCORE
  731. /// <summary>当前操作系统是 Windows。</summary>
  732. public static bool IsWindows { get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows); }
  733. /// <summary>当前操作系统是 OS X 或 macOS。</summary>
  734. public static bool IsOSX { get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX); }
  735. /// <summary>当前操作系统是 Linux。</summary>
  736. public static bool IsLinux { get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux); }
  737. #endif
  738. #endregion
  739. #region Exception
  740. internal static string Message(Exception ex)
  741. {
  742. if (ex == null) return null;
  743. try
  744. {
  745. var message = ex.Message;
  746. if (!string.IsNullOrEmpty(message)) return message;
  747. var typeName = ex.GetType().FullName;
  748. message = $"异常 <{typeName}> 包含空消息。";
  749. return message;
  750. }
  751. catch
  752. {
  753. var typeName = ex.GetType().FullName;
  754. return $"获取 <{typeName}> 的消息时再次发生了异常。";
  755. }
  756. }
  757. #endregion
  758. }
  759. }