using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.Reflection; namespace Masuit.Tools { public static class ObjectExtensions { private static readonly MethodInfo CloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); public static bool IsPrimitive(this Type type) { if (type == typeof(string)) { return true; } return type.IsValueType & type.IsPrimitive; } public static object DeepClone(this object originalObject) { return InternalCopy(originalObject, new Dictionary(new ReferenceEqualityComparer())); } public static T DeepClone(this T original) { return (T)DeepClone((object)original); } private static object InternalCopy(object originalObject, IDictionary visited) { if (originalObject == null) { return null; } var typeToReflect = originalObject.GetType(); if (IsPrimitive(typeToReflect)) { return originalObject; } if (visited.ContainsKey(originalObject)) { return visited[originalObject]; } if (typeof(Delegate).IsAssignableFrom(typeToReflect)) { return null; } var cloneObject = CloneMethod.Invoke(originalObject, null); if (typeToReflect.IsArray) { var arrayType = typeToReflect.GetElementType(); if (!IsPrimitive(arrayType)) { Array clonedArray = (Array)cloneObject; clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices)); } } visited.Add(originalObject, cloneObject); CopyFields(originalObject, visited, cloneObject, typeToReflect); RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect); return cloneObject; } private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary visited, object cloneObject, Type typeToReflect) { if (typeToReflect.BaseType != null) { RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType); CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate); } } private static void CopyFields(object originalObject, IDictionary visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func filter = null) { foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags)) { if (filter != null && !filter(fieldInfo)) { continue; } if (IsPrimitive(fieldInfo.FieldType)) { continue; } var originalFieldValue = fieldInfo.GetValue(originalObject); var clonedFieldValue = InternalCopy(originalFieldValue, visited); fieldInfo.SetValue(cloneObject, clonedFieldValue); } } /// /// 判断是否为null,null或0长度都返回true /// /// /// /// public static bool IsNullOrEmpty(this T value) where T : class { #region 1.对象级别 //引用为null bool isObjectNull = value is null; if (isObjectNull) { return true; } //判断是否为集合 var tempEnumerator = (value as IEnumerable)?.GetEnumerator(); if (tempEnumerator == null) return false;//这里出去代表是对象 且 引用不为null.所以为false #endregion 1.对象级别 #region 2.集合级别 //到这里就代表是集合且引用不为空,判断长度 //MoveNext方法返回tue代表集合中至少有一个数据,返回false就代表0长度 bool isZeroLenth = tempEnumerator.MoveNext() == false; if (isZeroLenth) return true; return isZeroLenth; #endregion 2.集合级别 } /// /// 转换成json字符串 /// /// /// /// public static string ToJsonString(this object obj, JsonSerializerSettings setting = null) { if (obj == null) return string.Empty; return JsonConvert.SerializeObject(obj, setting); } /// /// 严格比较两个对象是否是同一对象(判断引用) /// /// 自己 /// 需要比较的对象 /// 是否同一对象 public new static bool ReferenceEquals(this object @this, object o) { return object.ReferenceEquals(@this, o); } /// /// 是否是默认值 /// /// /// public static bool IsDefaultValue(this object value) { if (value == null) { return true; } var type = value.GetType(); if (type == typeof(bool)) { return (bool)value == false; } if (type.IsEnum) { return (int)value == 0; } if (type == typeof(DateTime)) { return (DateTime)value == default; } return double.Parse(value.ToString()) == 0; } /// /// 链式操作 /// /// /// /// /// /// public static T2 Next(this T1 source, Func action) { return action(source); } } class ReferenceEqualityComparer : EqualityComparer { public override bool Equals(object x, object y) { return ReferenceEquals(x, y); } public override int GetHashCode(object obj) { if (obj is null) return 0; return obj.GetHashCode(); } } static class ArrayExtensions { public static void ForEach(this Array array, Action action) { if (array.LongLength == 0) { return; } ArrayTraverse walker = new ArrayTraverse(array); do action(array, walker.Position); while (walker.Step()); } internal class ArrayTraverse { public int[] Position; private readonly int[] _maxLengths; public ArrayTraverse(Array array) { _maxLengths = new int[array.Rank]; for (int i = 0; i < array.Rank; ++i) { _maxLengths[i] = array.GetLength(i) - 1; } Position = new int[array.Rank]; } public bool Step() { for (int i = 0; i < Position.Length; ++i) { if (Position[i] < _maxLengths[i]) { Position[i]++; for (int j = 0; j < i; j++) { Position[j] = 0; } return true; } } return false; } } } }