/// <summary>
        /// Compares the properties of two objects of the same type and returns if all properties are equal.
        /// </summary>
        /// <param name="objectA">The first object to compare.</param>
        /// <param name="objectB">The second object to compre.</param>
        /// <param name="ignoreList">A list of property names to ignore from the comparison.</param>
        /// <returns><c>true</c> if all property values are equal, otherwise <c>false</c>.</returns>
        public static bool AreObjectsEqual(this object objectA, object objectB, params string[] ignoreList)
        {
            bool result;

            try
            {
                if (objectA != null && objectB != null)
                {
                    Type objectType;

                    objectType = objectA.GetType();

                    if (CanDirectlyCompare(objectType))
                    {
                        return(objectA.Equals(objectB));
                    }

                    result = true; // assume by default they are equal

                    foreach (PropertyInfo propertyInfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanRead && !ignoreList.Contains(p.Name)))
                    {
                        object valueA;
                        object valueB;

                        try
                        {
                            valueA = propertyInfo.GetValue(objectA, null);
                            valueB = propertyInfo.GetValue(objectB, null);

                            // if it is a primitive type, value type or implements IComparable, just directly try and compare the value
                            if (CanDirectlyCompare(propertyInfo.PropertyType))
                            {
                                if (!AreValuesEqual(valueA, valueB))
                                {
                                    Console.WriteLine(LocalizedResources.Instance().MismatchWithPropertyFound, objectType.FullName, propertyInfo.Name);
                                    result = false;
                                }
                            }
                            // if it implements IEnumerable, then scan any items
                            else if (typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType))
                            {
                                IEnumerable <object> collectionItems1;
                                IEnumerable <object> collectionItems2;
                                int collectionItemsCount1;
                                int collectionItemsCount2;

                                // null check
                                if (valueA == null && valueB != null || valueA != null && valueB == null)
                                {
                                    Console.WriteLine(LocalizedResources.Instance().MismatchWithPropertyFound, objectType.FullName, propertyInfo.Name);
                                    result = false;
                                }
                                else if (valueA != null && valueB != null)
                                {
                                    collectionItems1      = ((IEnumerable)valueA).Cast <object>();
                                    collectionItems2      = ((IEnumerable)valueB).Cast <object>();
                                    collectionItemsCount1 = collectionItems1.Count();
                                    collectionItemsCount2 = collectionItems2.Count();

                                    // check the counts to ensure they match
                                    if (collectionItemsCount1 != collectionItemsCount2)
                                    {
                                        Console.WriteLine(LocalizedResources.Instance().CollectionCountsForPropertyDoNotMatch, objectType.FullName, propertyInfo.Name);
                                        result = false;
                                    }
                                    // and if they do, compare each item... this assumes both collections have the same order
                                    else
                                    {
                                        for (int i = 0; i < collectionItemsCount1; i++)
                                        {
                                            object collectionItem1;
                                            object collectionItem2;
                                            Type   collectionItemType;

                                            collectionItem1    = collectionItems1.ElementAt(i);
                                            collectionItem2    = collectionItems2.ElementAt(i);
                                            collectionItemType = collectionItem1.GetType();

                                            if (CanDirectlyCompare(collectionItemType))
                                            {
                                                if (!AreValuesEqual(collectionItem1, collectionItem2))
                                                {
                                                    Console.WriteLine(LocalizedResources.Instance().ItemInPropertyCollectionDoesNotMatch, i, objectType.FullName, propertyInfo.Name);
                                                    result = false;
                                                }
                                            }
                                            else if (!AreObjectsEqual(collectionItem1, collectionItem2, ignoreList))
                                            {
                                                Console.WriteLine(LocalizedResources.Instance().ItemInPropertyCollectionDoesNotMatch, i, objectType.FullName, propertyInfo.Name);
                                                result = false;
                                            }
                                        }
                                    }
                                }
                            }
                            else if (propertyInfo.PropertyType.IsClass || propertyInfo.PropertyType.IsInterface)
                            {
                                if (!AreObjectsEqual(propertyInfo.GetValue(objectA, null), propertyInfo.GetValue(objectB, null), ignoreList))
                                {
                                    Console.WriteLine(LocalizedResources.Instance().MismatchWithPropertyFound, objectType.FullName, propertyInfo.Name);
                                    result = false;
                                }
                            }
                            else
                            {
                                Console.WriteLine(LocalizedResources.Instance().CannotCompareProperty, objectType.FullName, propertyInfo.Name);
                                result = false;
                            }
                        }
                        catch (System.Reflection.TargetParameterCountException te)
                        {
                            continue;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(LocalizedResources.Instance().CannotCompareValues, ex.Message);
                            result = false;
                        }
                    }
                }
                else
                {
                    result = object.Equals(objectA, objectB);
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(LocalizedResources.Instance().CannotCompareValues, ex.Message);
                result = false;
            }

            return(result);
        }