You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1004 lines
34 KiB
1004 lines
34 KiB
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
|
|
{
|
|
|
|
/// <summary>运行时实用工具。</summary>
|
|
public class RuntimeUtility
|
|
{
|
|
|
|
#region 反射操作
|
|
|
|
/// <summary>从外部加载对象。</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>克隆对象,创建新对象。可指定包含对象的属性和字段。</summary>
|
|
public static T Clone<T>(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;
|
|
}
|
|
|
|
/// <summary>对每个属性执行动作。</summary>
|
|
public static void ForEachProperties(object instance, Action<Property> 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<PropertyInfo>();
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>遍历属性。</summary>
|
|
public static void ForEachPublicProperties(object instance, Action<PropertyInfo> action)
|
|
{
|
|
if (instance != null && action != null) ForEachPublicProperties(instance.GetType(), action);
|
|
}
|
|
|
|
/// <summary>遍历属性。</summary>
|
|
public static void ForEachPublicProperties(Type type, Action<PropertyInfo> action)
|
|
{
|
|
if (type == null || action == null) return;
|
|
foreach (var property in type.GetProperties()) action.Invoke(property);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 反射验证
|
|
|
|
/// <summary>判断指定类型可序列化。</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>检查类型。</summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>检查类型。</summary>
|
|
public static bool TypeEquals<T>(object instance) => TypeEquals(instance, typeof(T));
|
|
|
|
/// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
|
|
public static T GetAttribute<T>(object target) where T : Attribute
|
|
{
|
|
if (target == null) return null;
|
|
try { return GetAttribute<T>(target.GetType()); } catch { return null; }
|
|
}
|
|
|
|
/// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
|
|
public static T GetAttribute<T>(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;
|
|
}
|
|
|
|
/// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
|
|
public static T GetAttribute<T>(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;
|
|
}
|
|
|
|
/// <summary>获取指定的首个特性,特性不存在时返回 Null 值。</summary>
|
|
public static T GetAttribute<T>(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;
|
|
}
|
|
|
|
/// <summary>获取一个值,指示该属性是否 static。</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>调用方法。</summary>
|
|
/// <exception cref="ArgumentException"></exception>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
/// <exception cref="MethodAccessException"></exception>
|
|
/// <exception cref="NotSupportedException"></exception>
|
|
/// <exception cref="TargetException"></exception>
|
|
/// <exception cref="TargetInvocationException"></exception>
|
|
/// <exception cref="TargetParameterCountException"></exception>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>调用泛型对象的 ToString() 方法。</summary>
|
|
public static string ToString<T>(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;
|
|
}
|
|
|
|
/// <summary>获取属性值。</summary>
|
|
/// <exception cref="ArgumentException"></exception>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
/// <exception cref="MethodAccessException"></exception>
|
|
/// <exception cref="NotSupportedException"></exception>
|
|
/// <exception cref="TargetException"></exception>
|
|
/// <exception cref="TargetInvocationException"></exception>
|
|
/// <exception cref="TargetParameterCountException"></exception>
|
|
public static T InvokeGet<T>(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
|
|
}
|
|
|
|
/// <summary>设置属性值。</summary>
|
|
/// <exception cref="ArgumentException"></exception>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
/// <exception cref="MethodAccessException"></exception>
|
|
/// <exception cref="NotSupportedException"></exception>
|
|
/// <exception cref="TargetException"></exception>
|
|
/// <exception cref="TargetInvocationException"></exception>
|
|
/// <exception cref="TargetParameterCountException"></exception>
|
|
public static void InvokeSet<T>(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
|
|
} /// <summary>指示方法是否存在于指定类型中。</summary>
|
|
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));
|
|
}
|
|
|
|
/// <summary>指示方法是否存在于指定类型中。</summary>
|
|
public static bool ExistIn<T>(MethodInfo method)
|
|
{
|
|
if (method == null) return false;
|
|
var type = typeof(T);
|
|
return type.Equals(method.DeclaringType.Equals(type));
|
|
}
|
|
|
|
/// <summary>判断指定类型具有特性。</summary>
|
|
private static bool ContainsAttribute<T>(object[] attributes) where T : Attribute
|
|
{
|
|
if (attributes == null) return false;
|
|
if (attributes.Length < 1) return false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>判断指定类型具有特性。</summary>
|
|
public static bool ContainsAttribute<T>(Type type, bool inherit = false) where T : Attribute
|
|
{
|
|
return type == null ? false : ContainsAttribute<T>(type.GetCustomAttributes(typeof(T), inherit));
|
|
}
|
|
|
|
/// <summary>判断指定属性具有特性。</summary>
|
|
public static bool ContainsAttribute<T>(PropertyInfo property, bool inherit = false) where T : Attribute
|
|
{
|
|
return property == null ? false : ContainsAttribute<T>(property.GetCustomAttributes(typeof(T), inherit));
|
|
}
|
|
|
|
/// <summary>判断基类。</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public static IEnumerable<Type> GetTypes(Assembly assembly)
|
|
{
|
|
if (assembly == null) return null;
|
|
|
|
var types = null as IEnumerable<Type>;
|
|
|
|
if (types == null)
|
|
{
|
|
try { types = assembly.GetExportedTypes(); }
|
|
catch { types = null; }
|
|
}
|
|
|
|
if (types == null)
|
|
{
|
|
try { types = assembly.GetTypes(); }
|
|
catch { types = null; }
|
|
}
|
|
|
|
return types;
|
|
}
|
|
|
|
/// <summary>能从外部创建对象实例。</summary>
|
|
public static bool CanNew<T>() => CanNew(typeof(T));
|
|
|
|
/// <summary>能从外部创建对象实例。</summary>
|
|
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
|
|
|
|
/// <summary>解析源对象。</summary>
|
|
public static Dictionary<string, string> GetOrigin(TextSet instance)
|
|
{
|
|
if (instance == null) return null;
|
|
return instance.Origin;
|
|
}
|
|
|
|
/// <summary>解析源对象。</summary>
|
|
public static Dictionary<string, object> GetOrigin(ObjectSet instance)
|
|
{
|
|
if (instance == null) return null;
|
|
return instance.Origin;
|
|
}
|
|
|
|
/// <summary>解析源对象。</summary>
|
|
public static Dictionary<string, T> GetOrigin<T>(ObjectSet<T> instance) // where T : ObjectSet<T>
|
|
{
|
|
if (instance == null) return null;
|
|
return instance.Origin;
|
|
}
|
|
|
|
/// <summary>安全转换为 List<<typeparamref name="T"/>> 对象。可指定排除 NULL 值元素。</summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public static List<T> ToList<T>(IEnumerable<T> objects, bool excludeNull = false)
|
|
{
|
|
var list = new List<T>();
|
|
if (objects != null)
|
|
{
|
|
foreach (var value in objects)
|
|
{
|
|
if (excludeNull && value == null) continue;
|
|
list.Add(value);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public static bool IsEmpty<T>(IEnumerable<T> objects)
|
|
{
|
|
if (objects == null) return true;
|
|
foreach (var i in objects) return false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public static bool NotEmpty<T>(IEnumerable<T> objects)
|
|
{
|
|
if (objects == null) return false;
|
|
foreach (var i in objects) return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>使用默认比较器判断相等。</summary>
|
|
public static bool Equals<T>(T a, T b) => EqualityComparer<T>.Default.Equals(a, b);
|
|
|
|
/// <summary>确定集合是否包含特定值</summary>
|
|
public static bool Contains<T>(IEnumerable<T> 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<T>) return ((ICollection<T>)objects).Contains(cell);
|
|
|
|
// cell 无效。
|
|
if (cell == null)
|
|
{
|
|
foreach (var i in objects)
|
|
{
|
|
if (i == null) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// cell 有效,进行默认比较。
|
|
var comparer = EqualityComparer<T>.Default;
|
|
foreach (var i in objects)
|
|
{
|
|
if (comparer.Equals(i, cell)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>获取集合中元素的数量。</summary>
|
|
public static int Count<T>(IEnumerable<T> objects)
|
|
{
|
|
if (objects == null) return 0;
|
|
|
|
// objects 实现了含有 Contains 方法的接口。
|
|
if (objects is ICollection<T>) return ((ICollection<T>)objects).Count;
|
|
|
|
var count = 0;
|
|
foreach (var cell in objects) count++;
|
|
return count;
|
|
}
|
|
|
|
/// <summary>对元素去重,且去除 NULL 值。</summary>
|
|
public static T[] Distinct<T>(IEnumerable<T> items)
|
|
{
|
|
if (items == null) throw new ArgumentNullException(nameof(items));
|
|
var count = Count(items);
|
|
var added = 0;
|
|
var array = new T[count];
|
|
|
|
var comparer = EqualityComparer<T>.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;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public static List<T> Sub<T>(IEnumerable<T> objects, long start = 0, long count = -1, Func<T> stuffer = null)
|
|
{
|
|
if (count == 0) return new List<T>();
|
|
|
|
var hasCount = count > 0L;
|
|
var output = new List<T>();
|
|
|
|
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
|
|
|
|
/// <summary>强制对所有代进行即时垃圾回收。</summary>
|
|
public static void Collect()
|
|
{
|
|
GC.Collect();
|
|
}
|
|
|
|
/// <summary>开始自动释放内存,默认间隔为 1000 毫秒。</summary>
|
|
public static void StartAutoFree()
|
|
{
|
|
KernelHelper.StartFree(1000);
|
|
}
|
|
|
|
/// <summary>开始自动释放内存,间隔以毫秒为单位。</summary>
|
|
public static void StartAutoFree(int milliseconds)
|
|
{
|
|
KernelHelper.StartFree(milliseconds);
|
|
}
|
|
|
|
/// <summary>停止自动释放内存。</summary>
|
|
public static void StopAutoFree()
|
|
{
|
|
KernelHelper.StopFree();
|
|
}
|
|
|
|
/// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
|
|
/// <returns>可能出现的错误信息。</returns>
|
|
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 { }
|
|
}
|
|
}
|
|
|
|
/// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
|
|
/// <returns>可能出现的错误信息。</returns>
|
|
public static void Dispose<T>(IEnumerable<T> objects, bool flush = false)
|
|
{
|
|
if (objects != null)
|
|
{
|
|
foreach (var i in objects) Dispose(i, flush);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Thread
|
|
|
|
/// <summary>停止线程。</summary>
|
|
public static void Abort(Thread thread)
|
|
{
|
|
if (thread == null) return;
|
|
try
|
|
{
|
|
if (thread.IsAlive) thread.Abort();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
/// <summary>阻塞当前线程,时长以毫秒为单位。</summary>
|
|
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(); }
|
|
}
|
|
|
|
/// <summary>在后台线程中执行,指定 Try 将忽略 Action 抛出的异常。</summary>
|
|
[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;
|
|
}
|
|
|
|
/// <summary>启动线程,指定 Try 将忽略 Action 抛出的异常。</summary>
|
|
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
|
|
|
|
/// <summary>列出当前域中的程序集。</summary>
|
|
public static Assembly[] ListLoadedAssemblies()
|
|
{
|
|
return AppDomain.CurrentDomain.GetAssemblies();
|
|
}
|
|
|
|
/// <summary>从指定的程序集加载资源。</summary>
|
|
/// <param name="name">资源的名称。</param>
|
|
/// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
|
|
/// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
|
|
/// <remarks>此方法不引发异常。</remarks>
|
|
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;
|
|
}
|
|
|
|
/// <summary>从程序集获取资源,读取到内存流。发生错误时返回 NULL 值,不引发异常。</summary>
|
|
/// <param name="name">资源的名称。</param>
|
|
/// <param name="assembly">程序集,为 NULL 值时指向 CallingAssembly。</param>
|
|
/// <returns>该资源的流,发生错误时返回 NULL 值。</returns>
|
|
/// <remarks>此方法不引发异常。</remarks>
|
|
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
|
|
|
|
/// <summary>设置缓存项。</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public static object CacheGet(string key)
|
|
{
|
|
if (TextUtility.IsEmpty(key)) return null;
|
|
|
|
var instance = MemoryCache.Default;
|
|
var entity = instance.Get(key, null);
|
|
return entity;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
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
|
|
|
|
/// <summary>获取当前应用程序所在目录的路径。</summary>
|
|
/// <remarks>
|
|
/// <para>程序示例: D:\App</para>
|
|
/// <para>网站示例: D:\App</para>
|
|
/// </remarks>
|
|
public static string ApplicationPath
|
|
{
|
|
get
|
|
{
|
|
#if NETSTD
|
|
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
#else
|
|
return AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>获取数据目录的路径。</summary>
|
|
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
|
|
|
|
/// <summary>获取启动目录的路径。</summary>
|
|
/// <remarks>
|
|
/// <para>调用: System.Windows.Forms.Application.StartupPath</para>
|
|
/// <para>示例: c:\windows\system32\inetsrv</para>
|
|
/// </remarks>
|
|
public static string StartupPath { get => Application.StartupPath; }
|
|
|
|
/// <summary>获取可执行文件的路径。</summary>
|
|
/// <remarks>
|
|
/// <para>调用: System.Windows.Forms.Application.ExecutablePath</para>
|
|
/// <para>示例: c:\windows\system32\inetsrv\w3wp.exe</para>
|
|
/// </remarks>
|
|
public static string ExecutablePath { get => Application.ExecutablePath; }
|
|
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// <para>System.AppDomain.CurrentDomain.BaseDirectory</para>
|
|
/// <para>D:\Website\</para>
|
|
/// </summary>
|
|
private static string CurrentDomainPath
|
|
{
|
|
get { return AppDomain.CurrentDomain.BaseDirectory; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>System.IO.Directory.GetCurrentDirectory()</para>
|
|
/// <para>c:\windows\system32\inetsrv</para>
|
|
/// </summary>
|
|
private static string CurrentDirectory
|
|
{
|
|
get { return Directory.GetCurrentDirectory(); } // System.Environment.CurrentDirectory
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</para>
|
|
/// <para>c:\windows\system32\inetsrv\w3wp.exe</para>
|
|
/// </summary>
|
|
private static string ProcessMainModule
|
|
{
|
|
get { return Process.GetCurrentProcess().MainModule.FileName; }
|
|
}
|
|
|
|
#if NETFX || NETCORE
|
|
|
|
#region System.Windows.Forms.Application
|
|
|
|
/// <summary>处理当前在消息队列中的所有 Windows 消息。</summary>
|
|
public static void DoEvents() => Application.DoEvents();
|
|
|
|
/// <summary>在没有窗体的情况下,在当前线程上开始运行标准应用程序消息循环。</summary>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
public static void ApplicationRun() => Application.Run();
|
|
|
|
/// <summary>在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。</summary>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
public static void ApplicationRun(Form form) => Application.Run(form);
|
|
|
|
/// <summary>关闭应用程序并立即启动一个新实例。</summary>
|
|
public static void ApplicationRestart() => Application.Restart();
|
|
|
|
/// <summary>通知所有消息泵必须终止,并且在处理了消息以后关闭所有应用程序窗口。</summary>
|
|
public static void ApplicationExit() => Application.Exit();
|
|
|
|
/// <summary>退出当前线程上的消息循环,并关闭该线程上的所有窗口。</summary>
|
|
public static void ApplicationExitThread() => Application.ExitThread();
|
|
|
|
#endregion
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Debug or Test
|
|
|
|
/// <summary>调用所有公共类,创建构造函数。</summary>
|
|
/// <param name="assembly">要搜索类的程序集,指定为 NULL 时将获取当前程序集。</param>
|
|
/// <param name="catchException">
|
|
/// <para>指定为 TRUE 时将使用 TRY 语句捕获异常;</para>
|
|
/// <para>指定为 FLASE 时发生异常将可能中断执行,可用于调试。</para></param>
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|