コード例 #1
0
ファイル: DCDataComparer.cs プロジェクト: komsa-ag/CoreWCF
        private bool CompareObjects(object lhObj, object rhObj)
        {
            if (lhObj == null && rhObj == null)
            {
                return(true);
            }

            if (lhObj == null || rhObj == null)
            {
                return(false);
            }

            Type lhObjType = lhObj.GetType();
            Type rhObjType = rhObj.GetType();

            //both objects have same circular reference
            if (lhsObjectHashTable[lhObj] != null && rhsObjectHashTable[rhObj] != null)
            {
                return(true);
            }
            // one object has circular ref, so not equal
            else if (lhsObjectHashTable[lhObj] != null || rhsObjectHashTable[rhObj] != null)
            {
                return(false);
            }

            DataContract lhDataContract = DataContract.GetDataContract(lhObjType);
            DataContract rhDataContract = DataContract.GetDataContract(rhObjType);

            //if either type is not serializable or DC, then above GetDataContract would throw
            //so both DataContracts are not null now
            if (!lhDataContract.Equals(rhDataContract))
            {
                return(false);
            }

            //lhDataContract and rhDataContract have same qname now (that's the Equals compare
            //enum, primitive, string and decimal can be compared by .Equals, note decimal is not a primitive
            //in this case, lhObjType should be equal to rhObjType
            if (lhObjType.IsEnum || lhObjType == typeof(Decimal) || lhObjType.IsPrimitive || lhObj is string)
            {
                System.Diagnostics.Debug.Assert(lhObjType == rhObjType, "types must be same for the compared objects when they are enum/primitive/string/decimal", string.Format("left type is {0}, right type is {1}", lhObjType, rhObjType));
                return(lhObj.Equals(rhObj));
            }
            else if (lhObjType.IsArray && rhObjType.IsArray)
            {
                Array lhArray = (Array)lhObj;
                Array rhArray = (Array)rhObj;

                if (lhArray.Length != rhArray.Length)
                {
                    return(false);
                }

                //indeces and bounds of the array to be compared
                //indeces is the current position
                Array indeces = Array.CreateInstance(typeof(int), lhArray.Rank);

                //bounds is the upper bounds of the array
                Array bounds           = Array.CreateInstance(typeof(int), lhArray.Rank);
                int   arrayTotalLength = 0;

                for (int i = 0; i < indeces.Length; i++)
                {
                    indeces.SetValue(0, i);
                    bounds.SetValue(lhArray.GetLength(i), i);
                    if (i == 0)
                    {
                        arrayTotalLength = lhArray.GetLength(0);
                    }
                    else
                    {
                        arrayTotalLength *= (int)lhArray.GetLength(i);
                    }
                }

                int  index  = 0;
                bool notEnd = true;

                //UNDONE: only need one condition, use both to double check here
                while (index < arrayTotalLength && notEnd)
                {
                    if (!this.CompareObjects(lhArray.GetValue((int[])indeces), rhArray.GetValue((int[])indeces)))
                    {
                        return(false);
                    }

                    //increase array indeces to the next element in the array
                    //always increment from the highest dimension
                    notEnd = this.IncIndex((int[])indeces, (int[])bounds, indeces.Length - 1);
                    index++;
                }

                return(true);
            }
            else
            {
                lhsObjectHashTable.Add(lhObj, lhObj);
                rhsObjectHashTable.Add(rhObj, rhObj);

                ClassDataContract lhClassDataContract = lhDataContract as ClassDataContract;
                ClassDataContract rhClassDataContract = rhDataContract as ClassDataContract;

                if (rhClassDataContract == null || lhClassDataContract == null)
                {
                    throw new Exception("type mismatch! not both are class/struct");
                }

                return(CompareDM(lhObj, lhClassDataContract, rhObj, rhClassDataContract));
            }
        }