Exemplo n.º 1
0
        private static SerializationMechanism GetSerializationMechanism(object data)
        {
            if (data == null)
            {
                return(SerializationMechanism.POCO);
            }
            SerializationMechanism att = SerializationMechanism.POCO;

            bool hasDataContractAttribute = data.GetType().GetCustomAttributes(typeof(DataContractAttribute), false).Length > 0;
            bool hasSerializableAttribute = data.GetType().IsSerializable;
            bool hasISerializable         = typeof(ISerializable).IsAssignableFrom(data.GetType());
            bool hasIXmlSerializable      = typeof(IXmlSerializable).IsAssignableFrom(data.GetType());

            if (
                (!hasDataContractAttribute) &&
                (!hasISerializable) &&
                (!hasIXmlSerializable) &&
                (!hasSerializableAttribute)
                )
            {
                att = SerializationMechanism.POCO;
            }
            else
            {
                if (hasDataContractAttribute || hasIXmlSerializable)
                {
                    att = SerializationMechanism.DataContractAttribute;
                }
                //CollectionDataContract is handled as part of DataContract containerTypeAttribute
                if (data.GetType().GetCustomAttributes(typeof(CollectionDataContractAttribute), false).Length > 0)
                {
                    hasDataContractAttribute = true;
                }

                //ISerializable interface is handled as part of Serializable containerTypeAttribute
                //since if a type implements ISerializable it must be marked with [Serializable] attribute
                if (data.GetType().GetInterface("ISerializable") != null)
                {
                    hasSerializableAttribute = true;
                }

                if (hasDataContractAttribute && hasISerializable)
                {
                    att = SerializationMechanism.DataContractAttribute;
                }
                else if (hasDataContractAttribute == true && hasISerializable == false)
                {
                    att = SerializationMechanism.DataContractAttribute;
                }
                else if (hasDataContractAttribute == false && (hasISerializable == true || hasSerializableAttribute == true))
                {
                    att = SerializationMechanism.SerializableAttribute;
                }
            }

            return(att);
        }
Exemplo n.º 2
0
        public static void CompareRecursively(object originalData, object deserializedData, bool approxComparisonForFloatingPointAnd64BitValues = false)
        {
            ComparisionType        cmpType = ComparisionType.DCS;
            SerializationMechanism att     = ComparisonHelper.GetSerializationMechanism(originalData);

            if (att.Equals(SerializationMechanism.POCO))
            {
                cmpType = ComparisionType.POCO;
            }
            ComparisonHelper.CompareData(originalData, deserializedData, att, cmpType);
        }
Exemplo n.º 3
0
        private static void CompareFields(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType)
        {
            //Compare fields
            //Non-public members are not serialized for POCO types
            BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;

            if (cmpType.Equals(ComparisionType.DCS))
            {
                flag = flag | BindingFlags.NonPublic;
            }

            foreach (System.Reflection.FieldInfo field in originalData.GetType().GetFields(flag))
            {
                object newData = field.GetValue(originalData);
                SerializationMechanism fieldAttribute = GetSerializationMechanism(newData);
                if (cmpType.Equals(ComparisionType.DCS))
                {
                    if (containerTypeAttribute.Equals(SerializationMechanism.DataContractAttribute))
                    {
                        if (
                            (field.GetCustomAttributes(typeof(DataMemberAttribute), false).Length > 0)
                            ||
                            (field.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length > 0)
                            )
                        {
                            //Pass attribute of the complex type for furthur evaluation
                            if (ComparisonHelper.IsComplexType(newData))
                            {
                                ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType);
                            }
                            else //Is a simple type
                            {
                                ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType);
                            }
                        }
                    }
                    else if (containerTypeAttribute.Equals(SerializationMechanism.SerializableAttribute))
                    {
                        //Do not compare [NonSerialized] members
                        if (!field.IsNotSerialized)
                        {
                            if (ComparisonHelper.IsComplexType(newData))
                            {
                                ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType);
                            }
                            else //Is a simple type
                            {
                                ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType);
                            }
                        }
                    }
                }
                else if (cmpType.Equals(ComparisionType.POCO))
                {
                    //ReadOnly fields should be ignored for POCO type
                    //Ignore member with [IgnoreDataMember] attribute on a POCO type
                    if ((!field.IsInitOnly) && (field.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false).Length == 0))
                    {
                        if (ComparisonHelper.IsComplexType(newData))
                        {
                            ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType);
                        }
                        else //Is a simple type
                        {
                            ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType);
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Iterates through the properties and invokes compare method
        /// </summary>
        /// <param name="originalData"></param>
        /// <param name="deserializedData"></param>
        /// <param name="containerTypeAttribute"></param>
        private static void CompareProperties(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType)
        {
            BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;

            //Include private fields for DCS types
            if (cmpType.Equals(ComparisionType.DCS))
            {
                flag = flag | BindingFlags.NonPublic;
            }

            foreach (System.Reflection.PropertyInfo property in originalData.GetType().GetProperties(flag))
            {
                object newData = property.GetValue(originalData, null);
                SerializationMechanism fieldAttribute = ComparisonHelper.GetSerializationMechanism(newData);
                if (cmpType.Equals(ComparisionType.DCS))
                {
                    if (containerTypeAttribute.Equals(SerializationMechanism.DataContractAttribute))
                    {
                        if (
                            (property.GetCustomAttributes(typeof(DataMemberAttribute), false).Length > 0)
                            ||
                            (property.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length > 0)
                            )
                        {
                            //Pass attribute of the complex type for furthur evaluation
                            if (IsComplexType(newData))
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType);
                            }
                            else //Is a simple type
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType);
                            }
                        }
                    }
                    else if (containerTypeAttribute.Equals(SerializationMechanism.SerializableAttribute))
                    {
                        if (property.GetCustomAttributes(typeof(NonSerializedAttribute), false).Length == 0)
                        {
                            //Pass attribute of the complex type for furthur evaluation
                            if (IsComplexType(newData))
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType);
                            }
                            else //Is a simple type, so pass Parents attribute
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType);
                            }
                        }
                    }
                }
                else if (cmpType.Equals(ComparisionType.POCO))
                {
                    //Ignore member with [IgnoreDataMember] attribute on a POCO type
                    if (property.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false).Length == 0)
                    {
                        //On POCO types, Properties which have both getter and setter will be serialized otherwise ignored
                        if (property.CanRead && property.CanWrite)
                        {
                            //Pass attribute of the complex type for furthur evaluation
                            if (IsComplexType(newData))
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType);
                            }
                            else //Is a simple type, so pass Parents attribute
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType);
                            }
                        }
                        else if (property.CanRead && !property.CanWrite) //Get-Only collection
                        {
                            //Pass attribute of the complex type for furthur evaluation
                            if (IsComplexType(newData))
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType);
                            }
                            else //Is a simple type, so pass Parents attribute
                            {
                                CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Throws an exception if mismatch is found
        /// </summary>
        /// <param name="originalData"></param>
        /// <param name="deserializedData"></param>
        private static void CompareData(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType)
        {
            if (originalData == null) // both are null, comparison succeeded
            {
                return;
            }

            if (originalData.GetType().Name.Equals(typeof(System.Runtime.Serialization.ExtensionDataObject).Name))
            {
                return;
            }

            //Fail if only one of the objects is null
            if ((null == originalData) != (null == deserializedData))
            {
                string message = string.Format("Comparision failed: Original data is {0}, deserialized data is {1}",
                                               originalData == null ? "null" : "not null", deserializedData == null ? "null" : "not null");

                if (originalData != null)
                {
                    message += string.Format("Contents of Original data are {0}", originalData.ToString());
                }
                if (deserializedData != null)
                {
                    message += string.Format("Contents of Deserialized data are {0}", deserializedData.ToString());
                }
                throw new Exception(message);
            }

            if (originalData is IObjectReference)
            {
                //All IObjectReference types implement Equals method which compares the object returned by GetRealObject method
                bool result = originalData.Equals(deserializedData);
                if (!result)
                {
                    throw new Exception("Comparision failed for type " + originalData.GetType().Name);
                }
                return;
            }

            //Return false if the type of the object is not same
            Type originalDataType     = originalData.GetType();
            Type deserializedDataType = deserializedData.GetType();

            if (!originalDataType.Equals(deserializedDataType))
            {
                throw new Exception(string.Format("Comparision failed : Original type {0} not same as deserialized type {1}", originalDataType.ToString(), deserializedDataType.ToString()));
            }

            object[] dataContractAttributes = originalDataType.GetCustomAttributes(typeof(DataContractAttribute), false);
            if (dataContractAttributes != null && dataContractAttributes.Length > 0)
            {
                DataContractAttribute dataContractAttribute = (DataContractAttribute)dataContractAttributes[0];
                if (dataContractAttribute.IsReference)
                {
                    return;
                }
            }

            MethodInfo equalsMethod = originalDataType.GetMethod("Equals", new Type[] { typeof(object) });

            #region "new object()"
            if (originalDataType == typeof(object))
            {
                return; // deserializedDataType == object as well; objects should be the same
            }
            #endregion

            #region String type
            else if (originalDataType.Equals(typeof(string)))
            {
                if (!originalData.Equals(deserializedData))
                {
                    throw new Exception(string.Format("Comparision failed: Original string data {0} is not same as deserialized string data {1}", originalData, deserializedData));
                }
            }
            #endregion

            #region XML types
            else if (originalDataType.Equals(typeof(XmlElement)) ||
                     originalDataType.Equals(typeof(XmlNode)))
            {
                string originalDataXml     = ((XmlNode)originalData).InnerXml;
                string deserializedDataXml = ((XmlNode)deserializedData).InnerXml;
                Trace.WriteLine(string.Format(LogMessage, originalDataType, originalDataXml, deserializedDataType, deserializedDataXml));
                if (!originalDataXml.Equals(deserializedDataXml))
                {
                    throw new Exception(string.Format("Comparision failed: Original XML data ({0}) is not the same as the deserialized XML data ({1})",
                                                      originalDataXml, deserializedDataXml));
                }
            }
            #endregion

            #region Special types
            else if (originalDataType == typeof(DBNull))
            {
                // only 1 possible value, DBNull.Value
                if ((((DBNull)originalData) == DBNull.Value) != (((DBNull)deserializedData) == DBNull.Value))
                {
                    throw new Exception(string.Format("Different instances of DBNull: original={0}, deserialized={1}", originalData, deserializedData));
                }
            }
            else if (originalDataType.Equals(typeof(DateTime)))
            {
                if (!(((DateTime)originalData).ToUniversalTime().Equals(((DateTime)deserializedData).ToUniversalTime())))
                {
                    throw new Exception(string.Format("Comparision failed: Original Datetime ticks {0} is not same as deserialized Datetime ticks {1}", ((DateTime)originalData).Ticks.ToString(), ((DateTime)deserializedData).Ticks.ToString()));
                }
            }
            else if (
                (originalDataType.Equals(typeof(TimeSpan))) ||
                (originalDataType.Equals(typeof(Uri))) ||
                (originalDataType.Equals(typeof(XmlQualifiedName))) ||
                (originalDataType.Equals(typeof(Guid))) ||
                (originalDataType.Equals(typeof(decimal))) ||
                (originalDataType.Equals(typeof(DateTimeOffset)))
                )
            {
                if (!originalData.Equals(deserializedData))
                {
                    throw new Exception(string.Format("Comparision failed : Original type data {0} is not same as deserialized type data {1}", originalData.ToString(), deserializedData.ToString()));
                }
            }

            #endregion

            #region Value Types

            else if (originalDataType.IsValueType)
            {
                //Value types can be Primitive types, Structs, Enums, Bool, User Defined Structs

                #region Primitive Types
                //Numeric types, bool
                if (originalDataType.IsPrimitive)
                {
                    bool different = !originalData.Equals(deserializedData);
                    if (different)
                    {
                        throw new Exception(string.Format("Comparision failed: Original primitive data {0} is not same as deserialized primitive data {1}", originalData.ToString(), deserializedData.ToString()));
                    }
                }
                #endregion

                #region Enum type
                else if (originalDataType.IsEnum)
                {
                    SerializationMechanism enumAttribute = GetSerializationMechanism(originalData);

                    //Verify member is marked with EnumMember attribute and compare the value with the Value property of the enum
                    if (enumAttribute.Equals(SerializationMechanism.DataContractAttribute))
                    {
                        if (ComparisonHelper.IsMemberMarkedWithEnumMember(originalData, cmpType))
                        {
                            //Verify this will work for all scenarios
                            if (!originalData.ToString().Equals(deserializedData.ToString()))
                            {
                                throw new Exception(string.Format("Comparision failed: Original enum data {0} is not same as deserialized enum data {1}", originalData.ToString(), deserializedData.ToString()));
                            }
                        }
                    }
                }
                #endregion

                //If not a Primitive and Enum, it has to be a struct
                #region User defined structs
                else
                {
                    #region Compare Fields
                    ComparisonHelper.CompareFields(originalData, deserializedData, containerTypeAttribute, cmpType);
                    #endregion

                    #region Compare properties
                    ComparisonHelper.CompareProperties(originalData, deserializedData, containerTypeAttribute, cmpType);
                    #endregion
                }
                #endregion
            }
            #endregion

            #region Types which know how to compare themselves
            else if (equalsMethod.DeclaringType == originalData.GetType())
            {
                // the type knows how to compare itself, we'll use it
                if (!originalData.Equals(deserializedData))
                {
                    throw new Exception(string.Format("Comparision failed: Original type data {0} is not same as deserialized type data {1}", originalData.ToString(), deserializedData.ToString()));
                }
            }
            #endregion

            #region IDictionary and IDictionary<T>
            //Compares generic as well as non-generic dictionary types
            //Hashtables
            else if (originalData is IDictionary)
            {
                if (deserializedData is IDictionary)
                {
                    IDictionaryEnumerator originalDataEnum     = ((IDictionary)originalData).GetEnumerator();
                    IDictionaryEnumerator deserializedDataEnum = ((IDictionary)deserializedData).GetEnumerator();
                    while (originalDataEnum.MoveNext())
                    {
                        deserializedDataEnum.MoveNext();
                        DictionaryEntry originalEntry     = originalDataEnum.Entry;
                        DictionaryEntry deserializedEntry = deserializedDataEnum.Entry;
                        //Compare the keys and then the values
                        CompareData(originalEntry.Key, deserializedEntry.Key, containerTypeAttribute, cmpType);
                        CompareData(originalEntry.Value, deserializedEntry.Value, containerTypeAttribute, cmpType);
                    }
                }
                else
                {
                    throw new Exception(string.Format("Comparision failed: Original IDictionary type {0} and deserialized IDictionary type {1} are not of same", originalDataType.GetType().ToString(), deserializedDataType.GetType().ToString()));
                }
            }
            #endregion

            #region IEnumerable,IList,ICollection,IEnumerable<t>,IList<T>,ICollection<T>
            //Array,Lists,Queues,Stacks etc
            else if (originalData is IEnumerable)
            {
                IEnumerator originalDataEnumerator     = ((IEnumerable)originalData).GetEnumerator();
                IEnumerator deserializedDataEnumerator = ((IEnumerable)deserializedData).GetEnumerator();
                if (null != originalDataEnumerator && null != deserializedDataEnumerator)
                {
                    while (originalDataEnumerator.MoveNext())
                    {
                        deserializedDataEnumerator.MoveNext();
                        CompareData(originalDataEnumerator.Current, deserializedDataEnumerator.Current, containerTypeAttribute, cmpType);
                    }
                }
                else
                {
                    throw new Exception(string.Format("Comparision failed: Original type {0} and deserialized type {1} are not IEnumerable", originalDataType.GetType().ToString(), deserializedDataType.GetType().ToString()));
                }
            }

            #endregion

            #region Class
            else if (originalDataType.IsClass)
            {
                #region Compare Fields
                ComparisonHelper.CompareFields(originalData, deserializedData, containerTypeAttribute, cmpType);
                #endregion

                #region Compare properties
                ComparisonHelper.CompareProperties(originalData, deserializedData, containerTypeAttribute, cmpType);
                #endregion
            }
            #endregion
        }