/// <summary> /// Equality function that properly handles arrays, /// lists, maps, lists of arrays, and maps of arrays. /// </summary> /// <remarks> /// <para> /// NOTE: For Sets, this relies on the equals method /// of the Set to do the right thing. This is a reasonable /// assumption since, in order for Sets to behave /// properly as Sets, their values must already have /// a proper implementation of equals. (Or they must /// be specialized Sets that define a custom comparator that /// knows how to do the right thing). The same holds true for Map keys. /// Map values, on the other hand, are compared (so Map values /// can be arrays). /// </para> /// </remarks> /// <param name="o1">The first object. May be null.</param> /// <param name="o2">The second object. May be null.</param> /// <returns>true iff the two objects are equal.</returns> public new static bool Equals(Object o1, Object o2) { if (o1 == o2) { //same object or both null return(true); } else if (o1 == null) { return(false); } else if (o2 == null) { return(false); } else if (o1 is Array) { Type clazz1 = o1.GetType(); Type clazz2 = o2.GetType(); if (!clazz1.Equals(clazz2)) { return(false); } Array array1 = (Array)o1; Array array2 = (Array)o2; int length1 = array1.Length; int length2 = array2.Length; if (length1 != length2) { return(false); } for (int i = 0; i < length1; i++) { Object el1 = array1.GetValue(i); Object el2 = array2.GetValue(i); if (!CollectionUtil.Equals(el1, el2)) { return(false); } } return(true); } else if (ReflectionUtil.IsParentTypeOf(typeof(IList <>), o1.GetType())) { Type parent1 = ReflectionUtil.FindInHierarchyOf(typeof(IList <>), o1.GetType()); Type parent2 = ReflectionUtil.FindInHierarchyOf(typeof(IList <>), o2.GetType()); if (!parent1.Equals(parent2)) { return(false); } Type[] genericArguments = parent1.GetGenericArguments(); Type collectionUtil = typeof(CollectionUtil); MethodInfo info = collectionUtil.GetMethod("ListsEqual"); info = info.MakeGenericMethod(genericArguments); Object rv = info.Invoke(null, new object[] { o1, o2 }); return((bool)rv); } else if (ReflectionUtil.IsParentTypeOf(typeof(IDictionary <,>), o1.GetType())) { Type parent1 = ReflectionUtil.FindInHierarchyOf(typeof(IDictionary <,>), o1.GetType()); Type parent2 = ReflectionUtil.FindInHierarchyOf(typeof(IDictionary <,>), o2.GetType()); if (!parent1.Equals(parent2)) { return(false); } Type[] genericArguments = parent1.GetGenericArguments(); Type collectionUtil = typeof(CollectionUtil); MethodInfo info = collectionUtil.GetMethod("DictionariesEqual"); info = info.MakeGenericMethod(genericArguments); Object rv = info.Invoke(null, new object[] { o1, o2 }); return((bool)rv); } else if (ReflectionUtil.IsParentTypeOf(typeof(ICollection <>), o1.GetType())) { Type parent1 = ReflectionUtil.FindInHierarchyOf(typeof(ICollection <>), o1.GetType()); Type parent2 = ReflectionUtil.FindInHierarchyOf(typeof(ICollection <>), o2.GetType()); if (!parent1.Equals(parent2)) { return(false); } Type[] genericArguments = parent1.GetGenericArguments(); Type collectionUtil = typeof(CollectionUtil); MethodInfo info = collectionUtil.GetMethod("SetsEqual"); info = info.MakeGenericMethod(genericArguments); Object rv = info.Invoke(null, new object[] { o1, o2 }); return((bool)rv); } else { return(o1.Equals(o2)); } }
/// <summary> /// Returns the generic type definition corresponding to this type. /// Will return the same type if this is already a generic type. /// </summary> /// <returns></returns> public SafeType <T> GetTypeErasure() { return(SafeType <T> .ForRawType(ReflectionUtil.GetTypeErasure(RawType))); }