internal ClassDataContract(Type type) : base(type) { object[] dataContractAttributes; bool hasDataContract; string name = null, ns = null; if (type.IsSerializable) { if (type.IsDefined(Globals.TypeOfDataContractAttribute, false)) { throw new Exception(String.Format("Type {0} has both [Serializable] and [DataContract]", type.FullName)); } hasDataContract = false; GetStableName(null, out name, out ns); } else { dataContractAttributes = type.GetCustomAttributes(Globals.TypeOfDataContractAttribute, false); if (dataContractAttributes != null && dataContractAttributes.Length > 0) { if (dataContractAttributes.Length > 1) { throw new Exception(String.Format("Type {0} has more than one [DataContract] attribute", type.FullName)); } hasDataContract = true; DataContractAttribute dataContractAttribute = (DataContractAttribute)dataContractAttributes[0]; GetStableName(dataContractAttribute, out name, out ns); } else { throw new Exception("Type has neither Serializable nor DataContract"); } } this.StableName = new XmlQualifiedName(name, ns); if (type.BaseType != null && type.BaseType != Globals.TypeOfObject && type.BaseType != Globals.TypeOfValueType) { this.BaseContract = (ClassDataContract)DataContract.GetDataContract(type.BaseType); } else { this.BaseContract = null; } ImportDataMembers(type, hasDataContract); }
internal ArrayDataContract(Type type) : base(type) { rank = type.GetArrayRank(); Type elementType = type; string arrayOfPrefix = String.Empty; while (elementType.IsArray) { arrayOfPrefix += "ArrayOf"; elementType = elementType.GetElementType(); } DataContract elementDataContract = DataContract.GetDataContract(elementType); string name = arrayOfPrefix + elementDataContract.StableName.Name; string ns = elementDataContract is PrimitiveDataContract ? Globals.SerializationNamespace : elementDataContract.StableName.Namespace; this.StableName = new XmlQualifiedName(name, ns); }
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)); } }