Beispiel #1
0
        /// <summary>
        /// Compares two class instances.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="comparer">The comparer.</param>
        /// <param name="incomparable">
        /// Whether objects are incomparable while no difference is found before both objects enter an infinite recursion, returns zero.
        /// </param>
        static int CompareObjects(object x, object y, PhpComparer comparer, out bool incomparable)
        {
            Debug.Assert(x != null && y != null);

            incomparable = false;

            // check for same instance
            if (ReferenceEquals(x, y))
            {
                return(0);
            }

            // check for different types
            var type_x = x.GetType().GetTypeInfo();
            var type_y = y.GetType().GetTypeInfo();

            if (type_x != type_y)
            {
                if (type_x.IsSubclassOf(type_y.AsType()))
                {
                    return(-1);
                }
                if (type_y.IsSubclassOf(type_x.AsType()))
                {
                    return(1);
                }

                incomparable = true;
                return(1); // they really are incomparable
            }

            // check for different number of fields
            int result = TypeMembersUtils.FieldsCount(x) - TypeMembersUtils.FieldsCount(y);

            if (result != 0)
            {
                return(result);
            }

            throw new NotImplementedException();
        }
Beispiel #2
0
        static int CompareObjects(object x, object y, PhpComparer comparer, out bool incomparable, ref HashSet <object> visited)
        {
            Debug.Assert(x != null && y != null);

            incomparable = false;

            // check for same instance
            if (ReferenceEquals(x, y))
            {
                return(0);
            }

            // check for different types
            var type_x = x.GetType();
            var type_y = y.GetType();

            if (type_x != type_y)
            {
                if (type_x.IsSubclassOf(type_y))
                {
                    return(-1);
                }
                if (type_y.IsSubclassOf(type_x))
                {
                    return(1);
                }

                incomparable = true;
                return(1); // they really are incomparable
            }

            // same type
            var phpt = type_x.GetPhpTypeInfo();

            // TODO: check PhpReference

            // compare properties:
            // the comparison operation stops and returns at the first unequal property found

            //if (visited == null)
            //{
            //    visited = new HashSet<object>();
            //}

            //if (visited.Add(x) == false && visited.Add(y) == false)
            //{
            //    // both objects already visited, break the recursion
            //    return 0;
            //}

            // TODO: infinite recursion prevention

            foreach (var p in phpt.GetDeclaredProperties())
            {
                if (p.IsStatic)
                {
                    continue;
                }

                var val_x = p.GetValue(null, x);
                var val_y = p.GetValue(null, y);

                var result = comparer.Compare(val_x, val_y);
                if (result != 0)
                {
                    return(result);
                }
            }

            // compare runtime properties:
            var arr_x = phpt.GetRuntimeFields(x);
            var arr_y = phpt.GetRuntimeFields(y);

            var count_x = arr_x != null ? arr_x.Count : 0;
            var count_y = arr_y != null ? arr_y.Count : 0;

            if (count_x != 0)
            {
                if (count_y == 0)
                {
                    return(count_x);
                }

                var enumerator = arr_x.GetFastEnumerator();
                while (enumerator.MoveNext())
                {
                    // TODO: if (!arr_y.TryGetValue(...)) ...
                    var result = comparer.Compare(enumerator.CurrentValue, arr_y[enumerator.CurrentKey]);
                    if (result != 0)
                    {
                        return(result);
                    }
                }
            }

            return(count_x - count_y);
        }
Beispiel #3
0
        /// <summary>
        /// Compares two class instances.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="comparer">The comparer.</param>
        /// <param name="incomparable">
        /// Whether objects are incomparable while no difference is found before both objects enter an infinite recursion, returns zero.
        /// </param>
        static int CompareObjects(object x, object y, PhpComparer comparer, out bool incomparable)
        {
            HashSet <object> visited = null;

            return(CompareObjects(x, y, comparer, out incomparable, ref visited));
        }