using Apewer.Internals; using Apewer.Models; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; #if NET40 || NET461 using System.Runtime.Caching; #endif #if NETFX || NETCORE using System.Windows.Forms; #endif namespace Apewer { /// 运行时实用工具。 public class RuntimeUtility { #region 反射操作 /// 从外部加载对象。 public static object CreateObject(string path, string type, bool ignoreCase) { try { var a = Assembly.LoadFrom(path); var t = a.GetType(type, false, ignoreCase); if (t != null) { var result = Activator.CreateInstance(t); return result; } } catch { } return null; } /// 克隆对象,创建新对象。可指定包含对象的属性和字段。 public static T Clone(T current, T failed = default(T), bool properties = true, bool fields = false) where T : new() { if (current == null) return default(T); var type = typeof(T); var target = new T(); foreach (var property in type.GetProperties()) { var getter = property.GetGetMethod(); var setter = property.GetSetMethod(); if (getter == null || setter == null) continue; var value = getter.Invoke(current, null); setter.Invoke(target, new object[] { value }); } foreach (var field in type.GetFields()) { var value = field.GetValue(current); field.SetValue(target, value); } return target; } /// 对每个属性执行动作。 public static void ForEachProperties(object instance, Action action, bool withNonPublic = true, bool withStatic = false) { if (instance == null || action == null) return; var type = instance.GetType(); if (type == null) return; var properties = new List(); properties.AddRange(type.GetProperties()); if (withNonPublic) properties.AddRange(type.GetProperties(BindingFlags.NonPublic)); foreach (var info in properties) { var arg = new Property() { Instance = instance, Type = type, Information = info, Getter = info.GetGetMethod(), Setter = info.GetSetMethod() }; if (arg.IsStatic && !withStatic) continue; action.Invoke(arg); } } /// 遍历属性。 public static void ForEachPublicProperties(object instance, Action action) { if (instance != null && action != null) ForEachPublicProperties(instance.GetType(), action); } /// 遍历属性。 public static void ForEachPublicProperties(Type type, Action action) { if (type == null || action == null) return; foreach (var property in type.GetProperties()) action.Invoke(property); } #endregion #region 反射验证 /// 判断指定类型可序列化。 public static bool CanSerialize(Type type, bool inherit = false) { if (type == null) return false; var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit); if (nsas != null && nsas.Length > 0) return false; var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit); if (sas != null && sas.Length > 0) return true; var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit); if (tas != null && tas.Length > 0) return true; return false; } /// 检查类型。 public static bool TypeEquals(object instance, Type type) { if (instance == null) return type == null ? true : false; if (instance is PropertyInfo) { return ((PropertyInfo)instance).PropertyType.Equals(type); } if (instance is MethodInfo) { return ((MethodInfo)instance).ReturnType.Equals(type); } return instance.GetType().Equals(type); } /// 检查类型。 public static bool TypeEquals(object instance) => TypeEquals(instance, typeof(T)); /// 获取指定的首个特性,特性不存在时返回 Null 值。 public static T GetAttribute(object target) where T : Attribute { if (target == null) return null; try { return GetAttribute(target.GetType()); } catch { return null; } } /// 获取指定的首个特性,特性不存在时返回 Null 值。 public static T GetAttribute(Type target, bool inherit = false) where T : Attribute { if (target == null) return null; try { var type = target; var attributes = type.GetCustomAttributes(typeof(T), inherit); if (attributes.LongLength > 0L) { var attribute = attributes[0] as T; return attribute; } } catch { } return null; } /// 获取指定的首个特性,特性不存在时返回 Null 值。 public static T GetAttribute(PropertyInfo property, bool inherit = false) where T : Attribute { if (property == null) return null; try { var type = property; var attributes = type.GetCustomAttributes(typeof(T), inherit); if (attributes.LongLength > 0L) { var attribute = attributes[0] as T; return attribute; } } catch { } return null; } /// 获取指定的首个特性,特性不存在时返回 Null 值。 public static T GetAttribute(MethodInfo methods, bool inherit = false) where T : Attribute { if (methods == null) return null; try { var type = methods; var attributes = type.GetCustomAttributes(typeof(T), inherit); if (attributes.LongLength > 0L) { var attribute = attributes[0] as T; return attribute; } } catch { } return null; } /// 获取一个值,指示该属性是否 static。 public static bool IsStatic(PropertyInfo property, bool withNonPublic = false) { if (property == null) return false; var getter = property.GetGetMethod(); if (getter != null) return getter.IsStatic; if (withNonPublic) { getter = property.GetGetMethod(true); if (getter != null) return getter.IsStatic; } var setter = property.GetSetMethod(); if (setter != null) return setter.IsStatic; if (withNonPublic) { setter = property.GetSetMethod(true); if (setter != null) return setter.IsStatic; } return false; } /// 调用方法。 /// /// /// /// /// /// /// public static object InvokeMethod(object instance, MethodInfo method, params object[] parameters) { if (instance == null || method == null) return null; { var pis = method.GetParameters(); if (pis == null || pis.Length < 1) { return method.Invoke(instance, null); } } { if (parameters == null) return method.Invoke(instance, new object[] { null }); return method.Invoke(instance, parameters); } } /// 调用泛型对象的 ToString() 方法。 public static string ToString(T target) { var type = typeof(T); var methods = type.GetMethods(); foreach (var method in methods) { if (method.Name != "ToString") continue; if (method.GetParameters().LongLength > 0L) continue; var result = (string)method.Invoke(target, null); return result; } return null; } /// 获取属性值。 /// /// /// /// /// /// /// public static T InvokeGet(object instance, PropertyInfo property) { if (instance == null || property == null || !property.CanRead) return default; #if NET20 || NET40 || NET461 var getter = property.GetGetMethod(); if (getter != null) { try { var value = getter.Invoke(instance, null); if (value != null) { return (T)value; } } catch { } } return default; #else var value = property.GetValue(instance); try { return (T)value; } catch { return default; } #endif } /// 设置属性值。 /// /// /// /// /// /// /// public static void InvokeSet(object instance, PropertyInfo property, T value) { if (instance == null || property == null || !property.CanWrite) return; #if NET20 || NET40 var setter = property.GetSetMethod(); if (setter != null) { try { setter.Invoke(instance, new object[] { value }); } catch { } } #else property.SetValue(instance, value); #endif } /// 指示方法是否存在于指定类型中。 public static bool ExistIn(MethodInfo method, Type type) { if (method == null) return false; if (type == null) return false; return type.Equals(method.DeclaringType.Equals(type)); } /// 指示方法是否存在于指定类型中。 public static bool ExistIn(MethodInfo method) { if (method == null) return false; var type = typeof(T); return type.Equals(method.DeclaringType.Equals(type)); } /// 判断指定类型具有特性。 private static bool ContainsAttribute(object[] attributes) where T : Attribute { if (attributes == null) return false; if (attributes.Length < 1) return false; return true; } /// 判断指定类型具有特性。 public static bool ContainsAttribute(Type type, bool inherit = false) where T : Attribute { return type == null ? false : ContainsAttribute(type.GetCustomAttributes(typeof(T), inherit)); } /// 判断指定属性具有特性。 public static bool ContainsAttribute(PropertyInfo property, bool inherit = false) where T : Attribute { return property == null ? false : ContainsAttribute(property.GetCustomAttributes(typeof(T), inherit)); } /// 判断基类。 public static bool IsInherits(Type child, Type @base) { // 检查参数。 if (child == null || @base == null) return false; // 忽略 System.Object。 var quantum = typeof(object); if (@base.Equals(quantum)) return true; if (child.Equals(quantum)) return true; // 循环判断基类。 var current = child; while (true) { var parent = current.BaseType; if (parent.Equals(@base)) return true; if (parent.Equals(quantum)) break; current = parent; } return false; } /// public static IEnumerable GetTypes(Assembly assembly) { if (assembly == null) return null; var types = null as IEnumerable; if (types == null) { try { types = assembly.GetExportedTypes(); } catch { types = null; } } if (types == null) { try { types = assembly.GetTypes(); } catch { types = null; } } return types; } /// 能从外部创建对象实例。 public static bool CanNew() => CanNew(typeof(T)); /// 能从外部创建对象实例。 public static bool CanNew(Type type) { if (type == null) return false; if (!type.IsClass && !type.IsValueType) return false; if (type.IsAbstract) return false; var constructors = type.GetConstructors(); foreach (var i in constructors) { if (i.IsPublic) { var parameters = i.GetParameters(); if (parameters.Length < 1) { return true; } } } return false; } #endregion #region Class Helper /// 解析源对象。 public static Dictionary GetOrigin(TextSet instance) { if (instance == null) return null; return instance.Origin; } /// 解析源对象。 public static Dictionary GetOrigin(ObjectSet instance) { if (instance == null) return null; return instance.Origin; } /// 解析源对象。 public static Dictionary GetOrigin(ObjectSet instance) // where T : ObjectSet { if (instance == null) return null; return instance.Origin; } /// 安全转换为 List<> 对象。可指定排除 NULL 值元素。 /// public static List ToList(IEnumerable objects, bool excludeNull = false) { var list = new List(); if (objects != null) { foreach (var value in objects) { if (excludeNull && value == null) continue; list.Add(value); } } return list; } /// public static bool IsEmpty(IEnumerable objects) { if (objects == null) return true; foreach (var i in objects) return false; return true; } /// public static bool NotEmpty(IEnumerable objects) { if (objects == null) return false; foreach (var i in objects) return true; return false; } /// 使用默认比较器判断相等。 public static bool Equals(T a, T b) => EqualityComparer.Default.Equals(a, b); /// 确定集合是否包含特定值 public static bool Contains(IEnumerable objects, T cell) { if (objects == null) return false; // 以 Object 类型对比。 // var a = (object)cell; // foreach (var i in objects) // { // var b = (object)i; // if (a == b) return true; // } // return false; // objects 实现了含有 Contains 方法的接口。 if (objects is ICollection) return ((ICollection)objects).Contains(cell); // cell 无效。 if (cell == null) { foreach (var i in objects) { if (i == null) return true; } return false; } // cell 有效,进行默认比较。 var comparer = EqualityComparer.Default; foreach (var i in objects) { if (comparer.Equals(i, cell)) return true; } return false; } /// 获取集合中元素的数量。 public static int Count(IEnumerable objects) { if (objects == null) return 0; // objects 实现了含有 Contains 方法的接口。 if (objects is ICollection) return ((ICollection)objects).Count; var count = 0; foreach (var cell in objects) count++; return count; } /// 对元素去重,且去除 NULL 值。 public static T[] Distinct(IEnumerable items) { if (items == null) throw new ArgumentNullException(nameof(items)); var count = Count(items); var added = 0; var array = new T[count]; var comparer = EqualityComparer.Default; foreach (var item in items) { if (item == null) continue; var contains = false; foreach (var i in array) { if (comparer.Equals(i, item)) { contains = true; break; } } if (contains) continue; array[added] = item; added++; } if (added < count) { var temp = new T[added]; Array.Copy(array, 0, temp, 0, added); array = temp; } return array; } /// public static List Sub(IEnumerable objects, long start = 0, long count = -1, Func stuffer = null) { if (count == 0) return new List(); var hasCount = count > 0L; var output = new List(); if (start < 0) { for (var i = start; i < 0; i++) { output.Add(stuffer == null ? default : stuffer()); if (hasCount && output.Count >= count) return output; } } if (objects != null) { var offset = 0L; foreach (var i in objects) { if (offset < start) { offset += 1L; continue; } offset += 1L; output.Add(i); if (hasCount && output.Count >= count) return output; } } while (hasCount && output.Count < count) { output.Add(stuffer == null ? default : stuffer()); } return output; } #endregion #region Collect & Dispose /// 强制对所有代进行即时垃圾回收。 public static void Collect() { GC.Collect(); } /// 开始自动释放内存,默认间隔为 1000 毫秒。 public static void StartAutoFree() { KernelHelper.StartFree(1000); } /// 开始自动释放内存,间隔以毫秒为单位。 public static void StartAutoFree(int milliseconds) { KernelHelper.StartFree(milliseconds); } /// 停止自动释放内存。 public static void StopAutoFree() { KernelHelper.StopFree(); } /// 执行与释放或重置非托管资源关联的应用程序定义的任务。 /// 可能出现的错误信息。 public static void Dispose(object @object, bool flush = false) { if (@object == null) return; var stream = @object as Stream; if (stream != null) { if (flush) { try { stream.Flush(); } catch { } } try { stream.Close(); } catch { } } var disposable = @object as IDisposable; if (disposable != null) { try { disposable.Dispose(); } catch { } } } /// 执行与释放或重置非托管资源关联的应用程序定义的任务。 /// 可能出现的错误信息。 public static void Dispose(IEnumerable objects, bool flush = false) { if (objects != null) { foreach (var i in objects) Dispose(i, flush); } } #endregion #region Thread /// 停止线程。 public static void Abort(Thread thread) { if (thread == null) return; try { if (thread.IsAlive) thread.Abort(); } catch { } } /// 阻塞当前线程,时长以毫秒为单位。 public static void Sleep(int milliseconds) { if (milliseconds > 0) Thread.Sleep(milliseconds); } private static void Invoke(Action action, bool @try = false) { if (action == null) return; if (@try) { try { action.Invoke(); } catch { } } else { action.Invoke(); } } /// 在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。 [MethodImpl(MethodImplOptions.NoInlining)] public static Thread InBackground(Action action, bool @try = false) { if (action == null) return null; var thread = new Thread(delegate (object v) { Invoke(() => ((Action)v)(), @try); }); thread.IsBackground = true; thread.Start(action); return thread; } /// 启动线程,指定 Try 将忽略 Action 抛出的异常。 public static Thread StartThread(Action action, bool background = true, bool @try = false) { if (action == null) return null; var thread = new Thread(new ThreadStart(() => Invoke(action, @try))); thread.IsBackground = background; thread.Start(); return thread; } #endregion #region Assembly /// 列出当前域中的程序集。 public static Assembly[] ListLoadedAssemblies() { return AppDomain.CurrentDomain.GetAssemblies(); } /// 从指定的程序集加载资源。 /// 资源的名称。 /// 程序集,为 NULL 值时指向 CallingAssembly。 /// 该资源的流,发生错误时返回 NULL 值。 /// 此方法不引发异常。 public static Stream OpenResource(string name, Assembly assembly = null) { var stream = null as Stream; try { var asm = assembly ?? Assembly.GetCallingAssembly(); stream = asm.GetManifestResourceStream(name); } catch { } return null; } /// 从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。 /// 资源的名称。 /// 程序集,为 NULL 值时指向 CallingAssembly。 /// 该资源的流,发生错误时返回 NULL 值。 /// 此方法不引发异常。 public static MemoryStream GetResource(string name, Assembly assembly = null) { var res = OpenResource(name, assembly); if (res == null) return null; var memory = new MemoryStream(); BinaryUtility.Read(res, memory); res.Dispose(); return memory; } #endregion #region Cache #if NET40 /// 设置缓存项。 public static bool CacheSet(string key, object value, int minutes = 60) { if (TextUtility.IsEmpty(key)) return false; if (minutes < 1) return false; var policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes((double)NumberUtility.RestrictValue(minutes, 0, 525600)); var instance = MemoryCache.Default; instance.Set(key, value, policy, null); return true; } /// public static object CacheGet(string key) { if (TextUtility.IsEmpty(key)) return null; var instance = MemoryCache.Default; var entity = instance.Get(key, null); return entity; } /// public static object CacheRemove(string key) { if (TextUtility.IsEmpty(key)) return null; var instance = MemoryCache.Default; var entity = instance.Remove(key, null); return entity; } #endif #endregion #region Application /// 获取当前应用程序所在目录的路径。 /// /// 程序示例: D:\App /// 网站示例: D:\App /// public static string ApplicationPath { get { #if NETSTD return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); #else return AppDomain.CurrentDomain.SetupInformation.ApplicationBase; #endif } } /// 获取数据目录的路径。 public static string DataPath { get { // 检查 App_Data 目录。 var appDir = ApplicationPath; var dataDir = Path.Combine(appDir, "app_data"); if (StorageUtility.DirectoryExists(dataDir)) return dataDir; // 获取并创建 Data 目录。 dataDir = Path.Combine(appDir, "data"); if (StorageUtility.AssureDirectory(dataDir)) return dataDir; // 使用 App 目录。 return appDir; } } #if NETFX || NETCORE /// 获取启动目录的路径。 /// /// 调用: System.Windows.Forms.Application.StartupPath /// 示例: c:\windows\system32\inetsrv /// public static string StartupPath { get => Application.StartupPath; } /// 获取可执行文件的路径。 /// /// 调用: System.Windows.Forms.Application.ExecutablePath /// 示例: c:\windows\system32\inetsrv\w3wp.exe /// public static string ExecutablePath { get => Application.ExecutablePath; } #endif /// /// System.AppDomain.CurrentDomain.BaseDirectory /// D:\Website\ /// private static string CurrentDomainPath { get { return AppDomain.CurrentDomain.BaseDirectory; } } /// /// System.IO.Directory.GetCurrentDirectory() /// c:\windows\system32\inetsrv /// private static string CurrentDirectory { get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory } /// /// System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName /// c:\windows\system32\inetsrv\w3wp.exe /// private static string ProcessMainModule { get { return Process.GetCurrentProcess().MainModule.FileName; } } #if NETFX || NETCORE #region System.Windows.Forms.Application /// 处理当前在消息队列中的所有 Windows 消息。 public static void DoEvents() => Application.DoEvents(); /// 在没有窗体的情况下,在当前线程上开始运行标准应用程序消息循环。 /// public static void ApplicationRun() => Application.Run(); /// 在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。 /// public static void ApplicationRun(Form form) => Application.Run(form); /// 关闭应用程序并立即启动一个新实例。 public static void ApplicationRestart() => Application.Restart(); /// 通知所有消息泵必须终止,并且在处理了消息以后关闭所有应用程序窗口。 public static void ApplicationExit() => Application.Exit(); /// 退出当前线程上的消息循环,并关闭该线程上的所有窗口。 public static void ApplicationExitThread() => Application.ExitThread(); #endregion #endif #endregion #region Debug or Test /// 调用所有公共类,创建构造函数。 /// 要搜索类的程序集,指定为 NULL 时将获取当前程序集。 /// /// 指定为 TRUE 时将使用 TRY 语句捕获异常; /// 指定为 FLASE 时发生异常将可能中断执行,可用于调试。 public static void InvokePublicClass(Assembly assembly = null, bool catchException = false) { const string Title = "Invoing Public Class"; Console.Title = Title; var before = DateTime.Now; Logger.Internals.Info(typeof(RuntimeUtility), "Started Invoke."); var types = GetTypes(assembly ?? Assembly.GetCallingAssembly()); foreach (var type in types) { if (!type.IsClass) continue; if (!type.IsPublic) continue; if (!CanNew(type)) continue; Logger.Internals.Info(typeof(RuntimeUtility), "Invoke " + type.FullName); Console.Title = type.FullName; if (catchException) { try { Activator.CreateInstance(type); } catch (Exception ex) { Logger.Internals.Exception(typeof(RuntimeUtility), ex); } } else { Activator.CreateInstance(type); } } Console.Title = Title; var after = DateTime.Now; var span = after - before; var milli = Convert.ToInt64(span.TotalMilliseconds); var duration = $"{milli / 1000D} 秒"; var result = "Finished Invoke.\n\n"; result += $" Duration: {duration}\n"; result += $" Started: {before.ToLucid()}\n"; result += $" Ended: {after.ToLucid()}\n"; Logger.Internals.Info(typeof(RuntimeUtility), result); } #endregion } }