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.

1117 lines
40 KiB

3 years ago
1 year ago
4 years ago
3 years ago
3 years ago
9 months ago
3 years ago
9 months ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 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
3 years ago
2 years ago
1 year ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
1 year ago
4 years ago
2 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
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
  1. using Apewer.Models;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Runtime.CompilerServices;
  8. using System.Text;
  9. using System.Threading;
  10. namespace Apewer
  11. {
  12. /// <summary>运行时实用工具。</summary>
  13. public static class RuntimeUtility
  14. {
  15. /// <summary>使用默认比较器判断相等。</summary>
  16. public static bool Equals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
  17. #region 反射操作
  18. /// <summary>从外部加载对象。</summary>
  19. public static object CreateObject(string path, string type, bool ignoreCase)
  20. {
  21. try
  22. {
  23. var a = Assembly.LoadFrom(path);
  24. var t = a.GetType(type, false, ignoreCase);
  25. if (t != null)
  26. {
  27. var result = Activator.CreateInstance(t);
  28. return result;
  29. }
  30. }
  31. catch { }
  32. return null;
  33. }
  34. /// <summary>对每个属性执行动作。</summary>
  35. public static void ForEachProperties(object instance, Action<Property> action, bool withNonPublic = true, bool withStatic = false)
  36. {
  37. if (instance == null || action == null) return;
  38. var type = instance.GetType();
  39. if (type == null) return;
  40. var properties = new List<PropertyInfo>();
  41. properties.AddRange(type.GetProperties());
  42. if (withNonPublic) properties.AddRange(type.GetProperties(BindingFlags.NonPublic));
  43. foreach (var info in properties)
  44. {
  45. var arg = new Property()
  46. {
  47. Instance = instance,
  48. Type = type,
  49. Information = info,
  50. Getter = info.GetGetMethod(),
  51. Setter = info.GetSetMethod()
  52. };
  53. if (arg.IsStatic && !withStatic) continue;
  54. action.Invoke(arg);
  55. }
  56. }
  57. #endregion
  58. #region Type
  59. /// <summary>判断指定类型可序列化。</summary>
  60. public static bool CanSerialize(Type type, bool inherit = false)
  61. {
  62. if (type == null) return false;
  63. var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit);
  64. if (nsas != null && nsas.Length > 0) return false;
  65. var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
  66. if (sas != null && sas.Length > 0) return true;
  67. var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit);
  68. if (tas != null && tas.Length > 0) return true;
  69. return false;
  70. }
  71. /// <summary>获取类型的完整名称。</summary>
  72. public static string FullName(Type type)
  73. {
  74. if (type == null) return null;
  75. var sb = new StringBuilder();
  76. var ns = type.Namespace;
  77. if (!string.IsNullOrEmpty(ns))
  78. {
  79. sb.Append(ns);
  80. sb.Append(".");
  81. }
  82. var name = type.Name;
  83. var g = name.IndexOf('`');
  84. if (g > -1) name = name.Substring(0, g);
  85. sb.Append(name);
  86. var gts = type.GetGenericArguments();
  87. if (gts != null && gts.Length > 0)
  88. {
  89. var ts = new List<string>(gts.Length);
  90. foreach (var gt in gts) ts.Add(FullName(gt));
  91. sb.Append("<");
  92. sb.Append(string.Join(",", ts.ToArray()));
  93. sb.Append(">");
  94. }
  95. return sb.ToString();
  96. }
  97. /// <summary>检查类型。</summary>
  98. public static bool TypeEquals(object instance, Type type)
  99. {
  100. if (instance == null) return type == null ? true : false;
  101. if (instance is PropertyInfo)
  102. {
  103. return ((PropertyInfo)instance).PropertyType.Equals(type);
  104. }
  105. if (instance is MethodInfo)
  106. {
  107. return ((MethodInfo)instance).ReturnType.Equals(type);
  108. }
  109. return instance.GetType().Equals(type);
  110. }
  111. /// <summary>检查类型。</summary>
  112. public static bool TypeEquals<T>(object instance) => TypeEquals(instance, typeof(T));
  113. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  114. public static T GetAttribute<T>(object target) where T : Attribute
  115. {
  116. if (target == null) return null;
  117. try { return GetAttribute<T>(target.GetType()); } catch { return null; }
  118. }
  119. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  120. public static T GetAttribute<T>(Type target, bool inherit = false) where T : Attribute
  121. {
  122. if (target == null) return null;
  123. try
  124. {
  125. var type = target;
  126. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  127. if (attributes.LongLength > 0L)
  128. {
  129. var attribute = attributes[0] as T;
  130. return attribute;
  131. }
  132. }
  133. catch { }
  134. return null;
  135. }
  136. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  137. public static T GetAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
  138. {
  139. if (property == null) return null;
  140. try
  141. {
  142. var type = property;
  143. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  144. if (attributes.LongLength > 0L)
  145. {
  146. var attribute = attributes[0] as T;
  147. return attribute;
  148. }
  149. }
  150. catch { }
  151. return null;
  152. }
  153. /// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
  154. public static T GetAttribute<T>(MethodInfo methods, bool inherit = false) where T : Attribute
  155. {
  156. if (methods == null) return null;
  157. try
  158. {
  159. var type = methods;
  160. var attributes = type.GetCustomAttributes(typeof(T), inherit);
  161. if (attributes.LongLength > 0L)
  162. {
  163. var attribute = attributes[0] as T;
  164. return attribute;
  165. }
  166. }
  167. catch { }
  168. return null;
  169. }
  170. /// <summary>获取一个值,指示该属性是否 static。</summary>
  171. public static bool IsStatic(PropertyInfo property, bool withNonPublic = false)
  172. {
  173. if (property == null) return false;
  174. var getter = property.GetGetMethod();
  175. if (getter != null) return getter.IsStatic;
  176. if (withNonPublic)
  177. {
  178. getter = property.GetGetMethod(true);
  179. if (getter != null) return getter.IsStatic;
  180. }
  181. var setter = property.GetSetMethod();
  182. if (setter != null) return setter.IsStatic;
  183. if (withNonPublic)
  184. {
  185. setter = property.GetSetMethod(true);
  186. if (setter != null) return setter.IsStatic;
  187. }
  188. return false;
  189. }
  190. /// <summary>调用方法。</summary>
  191. /// <exception cref="ArgumentException"></exception>
  192. /// <exception cref="InvalidOperationException"></exception>
  193. /// <exception cref="MethodAccessException"></exception>
  194. /// <exception cref="NotSupportedException"></exception>
  195. /// <exception cref="TargetException"></exception>
  196. /// <exception cref="TargetInvocationException"></exception>
  197. /// <exception cref="TargetParameterCountException"></exception>
  198. public static object Invoke(this MethodInfo method, object instance, params object[] parameters)
  199. {
  200. if (instance == null || method == null) return null;
  201. var pis = method.GetParameters();
  202. if (pis == null || pis.Length < 1) return method.Invoke(instance, null);
  203. if (parameters == null) return method.Invoke(instance, null);
  204. return method.Invoke(instance, parameters);
  205. }
  206. /// <summary>调用泛型对象的 ToString() 方法。</summary>
  207. public static string ToString<T>(T target)
  208. {
  209. var type = typeof(T);
  210. var methods = type.GetMethods();
  211. foreach (var method in methods)
  212. {
  213. if (method.Name != "ToString") continue;
  214. if (method.GetParameters().LongLength > 0L) continue;
  215. var result = (string)method.Invoke(target, null);
  216. return result;
  217. }
  218. return null;
  219. }
  220. /// <summary>获取属性值。</summary>
  221. /// <exception cref="ArgumentException"></exception>
  222. /// <exception cref="InvalidOperationException"></exception>
  223. /// <exception cref="MethodAccessException"></exception>
  224. /// <exception cref="NotSupportedException"></exception>
  225. /// <exception cref="TargetException"></exception>
  226. /// <exception cref="TargetInvocationException"></exception>
  227. /// <exception cref="TargetParameterCountException"></exception>
  228. public static T InvokeGet<T>(object instance, PropertyInfo property)
  229. {
  230. if (instance == null || property == null || !property.CanRead) return default;
  231. #if NET20 || NET40 || NET461
  232. var getter = property.GetGetMethod();
  233. if (getter != null)
  234. {
  235. try
  236. {
  237. var value = getter.Invoke(instance, null);
  238. if (value != null)
  239. {
  240. return (T)value;
  241. }
  242. }
  243. catch { }
  244. }
  245. return default;
  246. #else
  247. var value = property.GetValue(instance);
  248. try { return (T)value; } catch { return default; }
  249. #endif
  250. }
  251. /// <summary>设置属性值。</summary>
  252. /// <exception cref="ArgumentException"></exception>
  253. /// <exception cref="InvalidOperationException"></exception>
  254. /// <exception cref="MethodAccessException"></exception>
  255. /// <exception cref="NotSupportedException"></exception>
  256. /// <exception cref="TargetException"></exception>
  257. /// <exception cref="TargetInvocationException"></exception>
  258. /// <exception cref="TargetParameterCountException"></exception>
  259. public static void InvokeSet<T>(object instance, PropertyInfo property, T value)
  260. {
  261. if (instance == null || property == null || !property.CanWrite) return;
  262. #if NET20 || NET40
  263. var setter = property.GetSetMethod();
  264. if (setter != null)
  265. {
  266. try
  267. {
  268. setter.Invoke(instance, new object[] { value });
  269. }
  270. catch { }
  271. }
  272. #else
  273. property.SetValue(instance, value);
  274. #endif
  275. }
  276. /// <summary>指示方法是否存在于指定类型中。</summary>
  277. public static bool ExistIn(MethodInfo method, Type type)
  278. {
  279. if (method == null) return false;
  280. if (type == null) return false;
  281. return type.Equals(method.DeclaringType.Equals(type));
  282. }
  283. /// <summary>指示方法是否存在于指定类型中。</summary>
  284. public static bool ExistIn<T>(MethodInfo method)
  285. {
  286. if (method == null) return false;
  287. var type = typeof(T);
  288. return type.Equals(method.DeclaringType.Equals(type));
  289. }
  290. /// <summary>判断指定类型具有特性。</summary>
  291. private static bool Contains<T>(object[] attributes) where T : Attribute
  292. {
  293. if (attributes == null) return false;
  294. if (attributes.Length < 1) return false;
  295. var type = typeof(T);
  296. foreach (var attribute in attributes)
  297. {
  298. if (type.Equals(attribute.GetType())) return true;
  299. }
  300. return false;
  301. }
  302. /// <summary>判断指定类型具有特性。</summary>
  303. public static bool Contains<T>(ICustomAttributeProvider model, bool inherit = false) where T : Attribute
  304. {
  305. if (model == null) return false;
  306. var attributes = model.GetCustomAttributes(inherit);
  307. return Contains<T>(attributes);
  308. }
  309. /// <summary>判断基类。</summary>
  310. public static bool IsInherits(Type child, Type @base)
  311. {
  312. // 检查参数。
  313. if (child == null || @base == null) return false;
  314. if (child == @base) return false;
  315. // 检查 interface 类型。
  316. if (@base.IsInterface) return @base.IsAssignableFrom(child);
  317. // 忽略 System.Object。
  318. var quantum = typeof(object);
  319. if (@base.Equals(quantum)) return true;
  320. if (child.Equals(quantum)) return false;
  321. // 循环判断基类。
  322. var current = child;
  323. while (true)
  324. {
  325. var parent = current.BaseType;
  326. if (parent == null) return false;
  327. if (parent.Equals(@base)) return true;
  328. if (parent.Equals(quantum)) break;
  329. current = parent;
  330. }
  331. return false;
  332. }
  333. /// <summary></summary>
  334. public static Type[] GetTypes(Assembly assembly, bool onlyExported = false)
  335. {
  336. if (assembly == null) return null;
  337. try
  338. {
  339. return onlyExported ? assembly.GetExportedTypes() : assembly.GetTypes();
  340. }
  341. catch { }
  342. return new Type[0];
  343. }
  344. /// <summary>能从外部创建对象实例。</summary>
  345. public static bool CanNew<T>() => CanNew(typeof(T));
  346. /// <summary>能从外部创建对象实例。</summary>
  347. public static bool CanNew(Type type)
  348. {
  349. if (type == null) return false;
  350. if (!type.IsClass && !type.IsValueType) return false;
  351. if (type.IsAbstract) return false;
  352. var constructors = type.GetConstructors();
  353. foreach (var i in constructors)
  354. {
  355. if (i.IsPublic)
  356. {
  357. var parameters = i.GetParameters();
  358. if (parameters.Length < 1)
  359. {
  360. return true;
  361. }
  362. }
  363. }
  364. return false;
  365. }
  366. /// <summary>获取指定类型的默认值。</summary>
  367. public static object Default(Type type)
  368. {
  369. if (type == null || !type.IsValueType) return null;
  370. return Activator.CreateInstance(type);
  371. }
  372. /// <summary>判断指定对象是否为默认值。</summary>
  373. public static bool IsDefault(object value)
  374. {
  375. if (value.IsNull()) return true;
  376. var type = value.GetType();
  377. if (type.IsValueType) return value.Equals(Activator.CreateInstance(type));
  378. return false;
  379. }
  380. /// <summary>在程序集中枚举派生类型,可自定义检查器。</summary>
  381. public static Type[] DerivedTypes(Type baseType, Assembly assembly, Func<Type, bool> checker)
  382. {
  383. if (baseType == null) return new Type[0];
  384. if (assembly == null) return new Type[0];
  385. var types = GetTypes(assembly);
  386. var list = new List<Type>(types.Length);
  387. foreach (var type in types)
  388. {
  389. if (!IsInherits(type, baseType)) continue;
  390. if (checker != null && !checker(type)) continue;
  391. list.Add(type);
  392. }
  393. return list.ToArray();
  394. }
  395. /// <summary>是匿名类型。</summary>
  396. /// <exception cref="ArgumentNullException"></exception>
  397. public static bool IsAnonymousType(Type type)
  398. {
  399. if (type == null) throw new ArgumentNullException(nameof(type));
  400. // 类型是由编译器生成。
  401. if (!Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)) return false;
  402. // 是泛型。
  403. if (!type.IsGenericType) return false;
  404. // 名称。
  405. if (!type.Name.StartsWith("<>") || !type.Name.Contains("AnonymousType")) return false;
  406. // 私有。
  407. if (type.IsPublic) return false;
  408. return true;
  409. }
  410. /// <summary>获取数组元素的类型。</summary>
  411. /// <remarks>参数必须是正确的数组类型。</remarks>
  412. /// <exception cref="ArgumentException"></exception>
  413. /// <exception cref="ArgumentNullException"></exception>
  414. public static Type GetTypeOfArrayItem(Type arrayType)
  415. {
  416. if (arrayType == null) throw new ArgumentNullException(nameof(arrayType));
  417. if (!arrayType.BaseType.Equals(typeof(Array))) throw new ArgumentException($"参数 {arrayType} 不是有效的数组类型。");
  418. var methods = arrayType.GetMethods();
  419. foreach (var method in methods)
  420. {
  421. if (method.Name.ToLower() != "set") continue;
  422. var parameters = method.GetParameters();
  423. if (parameters.Length != 2) continue;
  424. var length = parameters[0].ParameterType;
  425. if (!length.Equals(typeof(int))) continue;
  426. var item = parameters[1].ParameterType;
  427. return item;
  428. }
  429. throw new ArgumentException($"参数 {arrayType} 不是有效的数组类型。");
  430. }
  431. /// <summary>是 Nullable&lt;T&gt; 类型。</summary>
  432. public static bool IsNullableType(this Type type)
  433. {
  434. if (type.IsGenericType && !type.IsGenericTypeDefinition)
  435. {
  436. Type genericTypeDefinition = type.GetGenericTypeDefinition();
  437. if ((object)genericTypeDefinition == typeof(Nullable<>))
  438. {
  439. return true;
  440. }
  441. }
  442. return false;
  443. }
  444. /// <summary>是 Nullable&lt;T&gt; 类型。</summary>
  445. public static bool IsNullableType(this Type type, out Type genericType)
  446. {
  447. if (type.IsGenericType && !type.IsGenericTypeDefinition)
  448. {
  449. Type genericTypeDefinition = type.GetGenericTypeDefinition();
  450. if ((object)genericTypeDefinition == typeof(Nullable<>))
  451. {
  452. genericType = type.GetGenericArguments()[0];
  453. return true;
  454. }
  455. }
  456. genericType = null;
  457. return false;
  458. }
  459. /// <summary>获取 Nullable&lt;T&gt; 实例的值。</summary>
  460. public static object GetNullableValue(object nullable)
  461. {
  462. var type = typeof(Nullable<>);
  463. var property = type.GetProperty("Value");
  464. var getter = property.GetGetMethod();
  465. var value = getter.Invoke(nullable, null);
  466. return value;
  467. }
  468. #endregion
  469. #region Collect & Dispose
  470. /// <summary>控制系统垃圾回收器(一种自动回收未使用内存的服务)。强制对所有代进行即时垃圾回收。</summary>
  471. public static void Collect() => GC.Collect();
  472. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  473. /// <returns>可能出现的错误信息。</returns>
  474. public static void Dispose(object instance, bool flush = false)
  475. {
  476. if (instance == null) return;
  477. var stream = instance as Stream;
  478. if (stream != null)
  479. {
  480. if (flush)
  481. {
  482. try { stream.Flush(); } catch { }
  483. }
  484. try { stream.Close(); } catch { }
  485. }
  486. var disposable = instance as IDisposable;
  487. if (disposable != null)
  488. {
  489. try
  490. {
  491. disposable.Dispose();
  492. }
  493. catch { }
  494. }
  495. }
  496. /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
  497. /// <returns>可能出现的错误信息。</returns>
  498. public static void Dispose<T>(IEnumerable<T> objects, bool flush = false)
  499. {
  500. if (objects != null)
  501. {
  502. foreach (var i in objects) Dispose(i, flush);
  503. }
  504. }
  505. #endregion
  506. #region Thread
  507. /// <summary>停止线程。</summary>
  508. public static void Abort(Thread thread)
  509. {
  510. if (thread == null) return;
  511. try
  512. {
  513. if (thread.IsAlive) thread.Abort();
  514. }
  515. catch { }
  516. }
  517. /// <summary>阻塞当前线程,时长以毫秒为单位。</summary>
  518. public static void Sleep(int milliseconds)
  519. {
  520. if (milliseconds > 0) Thread.Sleep(milliseconds);
  521. }
  522. private static void Invoke(Action action, bool @try = false)
  523. {
  524. if (action == null) return;
  525. if (@try)
  526. {
  527. try { action.Invoke(); } catch { }
  528. }
  529. else { action.Invoke(); }
  530. }
  531. /// <summary>在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。</summary>
  532. /// <param name="action">要执行的 Action。</param>
  533. /// <param name="try">忽略 Action 抛出的异常。</param>
  534. /// <remarks>对返回的 Thread 调用 Abort 可结束线程的执行。</remarks>
  535. [MethodImpl(MethodImplOptions.NoInlining)]
  536. public static Thread InBackground(Action action, bool @try = false)
  537. {
  538. if (action == null) return null;
  539. var thread = new Thread(delegate (object v)
  540. {
  541. Invoke(() => ((Action)v)(), @try);
  542. });
  543. thread.IsBackground = true;
  544. thread.Start(action);
  545. return thread;
  546. }
  547. /// <summary>在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。</summary>
  548. /// <param name="delay">延迟的毫秒数。</param>
  549. /// <param name="action">要执行的 Action。</param>
  550. /// <param name="try">忽略 Action 抛出的异常。</param>
  551. /// <remarks>对返回的 Thread 调用 Abort 可结束线程的执行。</remarks>
  552. [MethodImpl(MethodImplOptions.NoInlining)]
  553. public static Thread InBackground(int delay, Action action, bool @try = false)
  554. {
  555. if (action == null) return null;
  556. var thread = new Thread(delegate (object v)
  557. {
  558. if (delay > 0) Thread.Sleep(delay);
  559. Invoke(() => ((Action)v)(), @try);
  560. });
  561. thread.IsBackground = true;
  562. thread.Start(action);
  563. return thread;
  564. }
  565. /// <summary>启动线程,在新线程中执行。</summary>
  566. /// <param name="action">要执行的 Action。</param>
  567. /// <param name="background">设置线程为后台线程。</param>
  568. /// <param name="try">忽略 Action 抛出的异常。</param>
  569. /// <remarks>对返回的 Thread 调用 Abort 可结束线程的执行。</remarks>
  570. public static Thread StartThread(Action action, bool background = false, bool @try = false)
  571. {
  572. if (action == null) return null;
  573. var thread = new Thread(new ThreadStart(() => Invoke(action, @try)));
  574. thread.IsBackground = background;
  575. thread.Start();
  576. return thread;
  577. }
  578. /// <summary>经过指定时间(以毫秒为单位)后,在新线程(后台)中执行。</summary>
  579. /// <param name="action">要执行的 Action。</param>
  580. /// <param name="delay">调用 Action 之前延迟的时间量(以毫秒为单位)。</param>
  581. /// <param name="try">忽略 Action 抛出的异常。</param>
  582. /// <remarks>对返回的 Timer 调用 Dispose 可终止计时器,阻止调用。</remarks>
  583. public static Timer Timeout(Action action, int delay, bool @try = false)
  584. {
  585. if (action == null) return null;
  586. return new Timer((x) => Invoke((Action)x, @try), action, delay > 0 ? delay : 0, -1);
  587. }
  588. /// <summary>尝试在主线程调用。</summary>
  589. /// <exception cref="ArgumentNullException" />
  590. /// <exception cref="InvalidOperationException" />
  591. public static void OnMainThread(Action action)
  592. {
  593. if (action == null) throw new ArgumentNullException(nameof(action));
  594. var context = SynchronizationContext.Current;
  595. if (context == null) throw new InvalidOperationException("未获取到当前线程的同步上下文。");
  596. context.Send(state => { action.Invoke(); }, null);
  597. }
  598. /// <summary>尝试在主线程调用。</summary>
  599. /// <exception cref="ArgumentNullException" />
  600. /// <exception cref="InvalidOperationException" />
  601. public static TResult OnMainThread<TResult>(Func<TResult> func)
  602. {
  603. if (func == null) throw new ArgumentNullException(nameof(func));
  604. var context = SynchronizationContext.Current;
  605. if (context == null) throw new InvalidOperationException("未获取到当前线程的同步上下文。");
  606. var result = default(TResult);
  607. context.Send(state => result = func.Invoke(), null);
  608. return result;
  609. }
  610. #endregion
  611. #region Assembly
  612. /// <summary>列出当前域中的程序集。</summary>
  613. public static Assembly[] ListLoadedAssemblies()
  614. {
  615. return AppDomain.CurrentDomain.GetAssemblies();
  616. }
  617. /// <summary>从指定的程序集加载资源。</summary>
  618. /// <param name="name">资源的名称。</param>
  619. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  620. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  621. /// <remarks>此方法不引发异常。</remarks>
  622. public static Stream OpenResource(string name, Assembly assembly = null)
  623. {
  624. var stream = null as Stream;
  625. try
  626. {
  627. var asm = assembly ?? Assembly.GetCallingAssembly();
  628. stream = asm.GetManifestResourceStream(name);
  629. }
  630. catch { }
  631. return null;
  632. }
  633. /// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
  634. /// <param name="name">资源的名称。</param>
  635. /// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
  636. /// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
  637. /// <remarks>此方法不引发异常。</remarks>
  638. public static MemoryStream GetResource(string name, Assembly assembly = null)
  639. {
  640. var res = OpenResource(name, assembly);
  641. if (res == null) return null;
  642. var memory = new MemoryStream();
  643. BytesUtility.Read(res, memory);
  644. res.Dispose();
  645. return memory;
  646. }
  647. #if NETFRAMEWORK
  648. /// <summary>将代码生成为程序集。</summary>
  649. public static Assembly Compile(string code, bool executable = false, bool inMemory = true)
  650. {
  651. using (var cdp = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("C#"))
  652. {
  653. var cp = new System.CodeDom.Compiler.CompilerParameters();
  654. cp.ReferencedAssemblies.Add(typeof(void).Assembly.Location);
  655. cp.GenerateExecutable = false;
  656. cp.GenerateInMemory = true;
  657. cp.TempFiles = new System.CodeDom.Compiler.TempFileCollection(System.IO.Path.GetTempPath());
  658. var cr = cdp.CompileAssemblyFromSource(cp, code);
  659. if (cr.Errors.Count > 0) throw new Exception(cr.Errors[0].ErrorText);
  660. var assembly = cr.CompiledAssembly;
  661. return assembly;
  662. }
  663. }
  664. #endif
  665. #endregion
  666. #region Application
  667. private static Class<string> _AppPath = null;
  668. private static Class<string> _DataPath = null;
  669. private static Class<bool> _InIIS = null;
  670. /// <summary>当前应用程序由 IIS 托管。</summary>
  671. private static bool InIIS()
  672. {
  673. if (_InIIS != null) return _InIIS.Value;
  674. var dll = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
  675. var path1 = StorageUtility.CombinePath(ApplicationPath, dll);
  676. if (!File.Exists(path1))
  677. {
  678. var path2 = StorageUtility.CombinePath(ApplicationPath, "bin", dll);
  679. if (File.Exists(path2))
  680. {
  681. _InIIS = new Class<bool>(true);
  682. return true;
  683. }
  684. }
  685. _InIIS = new Class<bool>(false);
  686. return false;
  687. }
  688. /// <summary>获取当前应用程序所在目录的路径。</summary>
  689. /// <remarks>
  690. /// <para>程序示例: D:\App</para>
  691. /// <para>网站示例: D:\Website</para>
  692. /// </remarks>
  693. public static string ApplicationPath
  694. {
  695. get
  696. {
  697. var temp = _AppPath;
  698. if (!temp)
  699. {
  700. // AppDomain.CurrentDomain.BaseDirectory
  701. // AppDomain.CurrentDomain.SetupInformation.ApplicationBase
  702. // return AppDomain.CurrentDomain.BaseDirectory;
  703. #if NETSTD
  704. var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  705. #else
  706. var path = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
  707. #endif
  708. path = TextUtility.AssureEnds(path, "\\", false);
  709. path = TextUtility.AssureEnds(path, "/", false);
  710. temp = new Class<string>(path);
  711. _AppPath = temp;
  712. }
  713. return temp.Value;
  714. }
  715. }
  716. /// <summary>获取数据目录的路径。</summary>
  717. public static string DataPath
  718. {
  719. get
  720. {
  721. var temp = _DataPath;
  722. if (!temp)
  723. {
  724. var app = ApplicationPath;
  725. // 网站使用 App_Data 目录。
  726. var appData = Path.Combine(app, "app_data");
  727. if (Directory.Exists(appData))
  728. {
  729. temp = new Class<string>(appData);
  730. }
  731. else if (File.Exists(Path.Combine(app, "web.config")))
  732. {
  733. StorageUtility.AssureDirectory(appData);
  734. temp = new Class<string>(appData);
  735. }
  736. else
  737. {
  738. // 获取并创建 Data 目录。
  739. var data = Path.Combine(app, "data");
  740. if (StorageUtility.AssureDirectory(data)) temp = new Class<string>(data);
  741. else temp = new Class<string>(app);
  742. }
  743. _DataPath = temp;
  744. }
  745. return temp.Value;
  746. }
  747. }
  748. /// <summary>获取可执行文件的路径。</summary>
  749. /// <remarks>
  750. /// <para>调用: System.Windows.Forms.Application.ExecutablePath</para>
  751. /// <para>示例: c:\windows\system32\inetsrv\w3wp.exe</para>
  752. /// </remarks>
  753. public static string ExecutablePath
  754. {
  755. get
  756. {
  757. var entry = Assembly.GetEntryAssembly();
  758. if (entry == null) return null;
  759. var escapedCodeBase = entry.EscapedCodeBase;
  760. var uri = new Uri(escapedCodeBase);
  761. if (uri.Scheme == "file") return uri.LocalPath + uri.Fragment;
  762. return uri.ToString();
  763. }
  764. }
  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. /// <summary>捕获异常。</summary>
  790. /// <exception cref="ArgumentNullException" />
  791. public static void CatchException(Action<Exception> callback)
  792. {
  793. if (callback == null) throw new ArgumentNullException(nameof(callback));
  794. AppDomain.CurrentDomain.UnhandledException += (s, e) => callback(e.ExceptionObject as Exception);
  795. #if !NET20
  796. System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (s, e) => callback(e.Exception);
  797. #endif
  798. #if NETFRAMEWORK
  799. System.Windows.Forms.Application.SetUnhandledExceptionMode(System.Windows.Forms.UnhandledExceptionMode.CatchException);
  800. System.Windows.Forms.Application.ThreadException += (s, e) => callback(e.Exception);
  801. #endif
  802. }
  803. #endregion
  804. #region Evaluate
  805. /// <summary>评估 Action 的执行时间,单位为毫秒。</summary>
  806. public static long Evaluate(Action action)
  807. {
  808. if (action == null) return 0;
  809. var stopwatch = new Stopwatch();
  810. stopwatch.Start();
  811. action.Invoke();
  812. stopwatch.Stop();
  813. return stopwatch.ElapsedMilliseconds;
  814. }
  815. #endregion
  816. #region Console
  817. /// <summary>获取或设置控制台标题。</summary>
  818. public static string Title
  819. {
  820. get { try { return Console.Title; } catch { return null; } }
  821. set { try { Console.Title = value; } catch { } }
  822. }
  823. /// <summary>设置在控制台中按 CTRL + C 时的方法。</summary>
  824. public static void CtrlCancel(Func<bool> exit)
  825. {
  826. const string postfix = " - 按 CTRL + C 可安全退出";
  827. var title = Title ?? "";
  828. if (!title.EndsWith(postfix))
  829. {
  830. title = title + postfix;
  831. Title = title;
  832. }
  833. if (exit == null) return;
  834. try { Console.CancelKeyPress += (s, e) => e.Cancel = !exit(); } catch { }
  835. }
  836. /// <summary>调用所有公共类,创建构造函数。</summary>
  837. /// <param name="assembly">要搜索类的程序集,指定为 NULL 时将获取当前程序集。</param>
  838. /// <param name="catchException">
  839. /// <para>指定为 TRUE 时将使用 TRY 语句捕获异常;</para>
  840. /// <para>指定为 FLASE 时发生异常将可能中断执行,可用于调试。</para></param>
  841. public static void InvokePublicClass(Assembly assembly = null, bool catchException = false)
  842. {
  843. const string Title = "Invoing Public Class";
  844. RuntimeUtility.Title = Title;
  845. var before = DateTime.Now;
  846. Logger.Internals.Info(typeof(RuntimeUtility), "Started Invoke.");
  847. var types = GetTypes(assembly ?? Assembly.GetCallingAssembly());
  848. foreach (var type in types)
  849. {
  850. if (!type.IsClass) continue;
  851. if (!type.IsPublic) continue;
  852. if (!CanNew(type)) continue;
  853. Logger.Internals.Info(typeof(RuntimeUtility), "Invoke " + type.FullName);
  854. RuntimeUtility.Title = type.FullName;
  855. try
  856. {
  857. Activator.CreateInstance(type);
  858. }
  859. catch (Exception ex)
  860. {
  861. var ex2 = ex.InnerException ?? ex;
  862. Logger.Internals.Exception(ex2, typeof(RuntimeUtility));
  863. if (!catchException) throw ex2;
  864. }
  865. }
  866. RuntimeUtility.Title = Title;
  867. var after = DateTime.Now;
  868. var span = after - before;
  869. var milli = Convert.ToInt64(span.TotalMilliseconds);
  870. var duration = $"{milli / 1000D} 秒";
  871. var result = "Finished Invoke.\n\n";
  872. result += $" Duration: {duration}\n";
  873. result += $" Started: {before.Lucid()}\n";
  874. result += $" Ended: {after.Lucid()}\n";
  875. Logger.Internals.Info(typeof(RuntimeUtility), result);
  876. }
  877. #endregion
  878. #region System
  879. /// <summary>结束当前进程。</summary>
  880. public static void Exit()
  881. {
  882. Environment.Exit(0);
  883. Process.GetCurrentProcess().Kill();
  884. }
  885. /// <summary>当前操作系统是 Windows。</summary>
  886. public static bool IsWindows
  887. {
  888. #if NETFRAMEWORK
  889. get => Environment.OSVersion.Platform == PlatformID.Win32NT;
  890. #else
  891. get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
  892. #endif
  893. }
  894. /// <summary>当前操作系统是 OS X 或 macOS。</summary>
  895. public static bool IsOSX
  896. {
  897. #if NETFRAMEWORK
  898. get => Environment.OSVersion.Platform == PlatformID.MacOSX;
  899. #else
  900. get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX);
  901. #endif
  902. }
  903. /// <summary>当前操作系统是 Linux。</summary>
  904. public static bool IsLinux
  905. {
  906. #if NETFRAMEWORK
  907. get => Environment.OSVersion.Platform == PlatformID.Unix;
  908. #else
  909. get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux);
  910. #endif
  911. }
  912. #if NETFRAMEWORK
  913. /// <summary>当前进程是以管理员身份运行。</summary>
  914. public static bool IsAdministratorRole()
  915. {
  916. var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
  917. var principal = new System.Security.Principal.WindowsPrincipal(identity);
  918. var result = principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
  919. return result;
  920. }
  921. #endif
  922. #endregion
  923. #region Exception
  924. /// <summary>读取调用堆栈。</summary>
  925. public static string[] StackTrace()
  926. {
  927. var trace = new StackTrace(true);
  928. var frames = trace.GetFrames();
  929. var ab = new ArrayBuilder<string>();
  930. foreach (var frame in frames)
  931. {
  932. // 滤除当前方法。
  933. var method = frame.GetMethod();
  934. if (method == null) continue;
  935. var type = method.DeclaringType;
  936. if (type == null) continue;
  937. var value = $"{method.DeclaringType.FullName}.{method.Name}";
  938. ab.Add(value);
  939. }
  940. return ab.Export();
  941. }
  942. internal static string Message(Exception ex)
  943. {
  944. if (ex == null) return null;
  945. try
  946. {
  947. var message = ex.Message;
  948. if (!string.IsNullOrEmpty(message)) return message;
  949. var typeName = ex.GetType().FullName;
  950. message = $"异常 <{typeName}> 包含空消息。";
  951. return message;
  952. }
  953. catch
  954. {
  955. var typeName = ex.GetType().FullName;
  956. return $"获取 <{typeName}> 的消息时再次发生了异常。";
  957. }
  958. }
  959. #endregion
  960. }
  961. }