/// <summary>
        /// Get validator for a member
        /// </summary>
        /// <param name="config"></param>
        /// <param name="info"></param>
        /// <param name="objectType"></param>
        /// <returns></returns>
        public static BaseTypeComparer CustomValidatorForMember(ComparisonConfig config, MemberInfo info, Type objectType)
        {
            BaseTypeComparer customValidator = null;

            if (config.CustomPropertyComparers.Count == 0)
            {
                return(customValidator);
            }

            //Get by objecttype.membername
            customValidator = GetValidatorByName(config, objectType.Name + "." + info.Name);
            if (customValidator != null)
            {
                return(customValidator);
            }

            //Get by declaringType.membername
            if (info.DeclaringType != null)
            {
                customValidator = GetValidatorByName(config, info.DeclaringType.Name + "." + info.Name);
                if (customValidator != null)
                {
                    return(customValidator);
                }
            }

            //Get exactly by the name of the member
            customValidator = GetValidatorByName(config, info.Name);
            if (customValidator != null)
            {
                return(customValidator);
            }

            return(customValidator);
        }
        /// <summary>
        /// Get validator for a member of an expando object
        /// </summary>
        /// <param name="config"></param>
        /// <param name="name"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static BaseTypeComparer CustomValidatorForDynamicMember(ComparisonConfig config, string name, Type type)
        {
            BaseTypeComparer customValidator = null;

            if (config.CustomPropertyComparers.Count == 0)
            {
                return(customValidator);
            }

            //Only compare specific member names
            customValidator = GetValidatorByName(config, name);
            if (customValidator != null)
            {
                return(customValidator);
            }

            //Get by type.membername
            customValidator = GetValidatorByName(config, type.Name + "." + name);
            if (customValidator != null)
            {
                return(customValidator);
            }

            return(customValidator);
        }
        /// <summary>
        /// Compare two objects
        /// </summary>
        public bool Compare(CompareParms parms)
        {
            try
            {
                if (parms.Object1 == null && parms.Object2 == null)
                {
                    return(true);
                }

                Type t1 = parms.Object1 != null?parms.Object1.GetType() : null;

                Type t2 = parms.Object2 != null?parms.Object2.GetType() : null;

                BaseTypeComparer customComparer = parms.Config.CustomComparers.FirstOrDefault(o => o.IsTypeMatch(t1, t2));

                if (customComparer != null)
                {
                    customComparer.CompareType(parms);
                }
                else
                {
                    BaseTypeComparer typeComparer = TypeComparers.FirstOrDefault(o => o.IsTypeMatch(t1, t2));

                    if (typeComparer != null)
                    {
                        if (parms.Config.IgnoreObjectTypes || !TypesDifferent(parms, t1, t2))
                        {
                            typeComparer.CompareType(parms);
                        }
                    }
                    else
                    {
                        if (EitherObjectIsNull(parms))
                        {
                            return(false);
                        }

                        if (!parms.Config.IgnoreObjectTypes && t1 != null)
                        {
                            throw new NotSupportedException("Cannot compare object of type " + t1.Name);
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                if (!parms.Config.IgnoreObjectDisposedException)
                {
                    throw;
                }

                return(true);
            }

            return(parms.Result.AreEqual);
        }
        public void CustomPropertyComparer <TClass>(Expression <Func <TClass, object> > customProperty, BaseTypeComparer validator)
        {
            LambdaExpression lambda = customProperty;
            MemberExpression memberExpression;

            if (lambda.Body is UnaryExpression unaryExpression)
            {
                memberExpression = unaryExpression.Operand as MemberExpression ??
                                   // catches methods, maybe other things
                                   throw new ArgumentException(
                                             $"Custom property comparer can only be used with properties. {customProperty} is not a property.");
            }
            else
            {
                memberExpression = (MemberExpression)lambda.Body;
            }

            var propInfo = memberExpression.Member as PropertyInfo;

            if (propInfo == null)
            // catches fields, maybe other things
            {
                throw new ArgumentException($"Custom property comparer can only be used with properties. {customProperty} is not a property.");
            }

            var name = propInfo.Name;

            CustomPropertyComparers.Add(typeof(TClass).Name + "." + name, validator);
        }