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.

1013 lines
36 KiB

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