/// <summary>
        /// Get Parse Attribute.
        /// </summary>
        /// <param name="member">The Member.</param>
        /// <param name="actualTypeInheritanceHierarchy">Actual Type Inheritance Hierarchy.</param>
        /// <returns>Parse Attribute.</returns>
        public static ParseAttribute GetParseAttribute(this MemberInfo member, Type[] actualTypeInheritanceHierarchy)
        {
            ParseAttribute pa = _parseAttributeCache.GetOrAdd(member, (m) => GetParseAttributeInternal(m, actualTypeInheritanceHierarchy));

            //ParseAttribute pa;
            //if (!_parseAttributeCache.Value.TryGetValue(member, out pa))
            //{
            //    pa = GetParseAttributeInternal(member, actualTypeInheritanceHierarchy);
            //    _parseAttributeCache.Value.Add(member, pa);
            //}
            return(pa);
        }
        /// <summary>
        /// Gets the default or declared parse attribute for the specified member.
        /// </summary>
        /// <param name="member">The Member.</param>
        /// <param name="actualTypeInheritanceHierarchy">actualTypeInheritanceHierarchy</param>
        /// <returns>Parse Attribute.</returns>
        private static ParseAttribute GetParseAttributeInternal(this MemberInfo member, Type[] actualTypeInheritanceHierarchy)
        {
            // march up the stack, starting at the actual type's base. If we find the member before we find a ParseExplicit, we're ok to parse this.
            // If we find a parseExplicity first, then we know we can't parse this member.  If a member is declared in the first class that we see ParseExplicit,
            // keep it, because we define ParseExplicit as "keep for this and all derived types"
            for (int i = actualTypeInheritanceHierarchy.Length - 1; i >= 0; i--)
            {
                if (member.DeclaringType.Equals(actualTypeInheritanceHierarchy[i]))
                {
                    break;
                }
                if (actualTypeInheritanceHierarchy[i].DoNotParseInherited())
                {
                    return(DefaultIgnoreAttribute);
                }
            }

            ParseAttribute parseAttribute = (ParseAttribute)Attribute.GetCustomAttribute(member, typeof(ParseAttribute));

            if (IsIndexer(member))
            {
                Helper.CheckCondition <ParseException>(parseAttribute == null || parseAttribute.Action == ParseAction.Ignore, "Can't parse an Indexer.");
                return(DefaultIgnoreAttribute);
            }

            PropertyInfo property = member as PropertyInfo;

            if (parseAttribute == null)
            {
                FieldInfo field = member as FieldInfo;
                if (field != null)
                {
                    return(field.IsPublic ? DefaultOptionalAttribute : DefaultIgnoreAttribute);
                }
                else if (property != null)
                {
                    parseAttribute = property.GetGetMethod() != null && property.GetSetMethod() != null && property.GetGetMethod().IsPublic&& property.GetSetMethod().IsPublic ?  // either will be null if don't exist or non-public
                                     DefaultOptionalAttribute : DefaultIgnoreAttribute;
                }
                else
                {
                    parseAttribute = DefaultIgnoreAttribute;
                }
            }
            return(parseAttribute);
        }
        /// <summary>
        /// Get Default Parameters Or Null.
        /// </summary>
        /// <param name="member">The Member.</param>
        /// <returns>Default Parameter or null.</returns>
        public static string GetDefaultParametersOrNull(this MemberInfo member)
        {
            ParseAttribute parseAttribute = (ParseAttribute)Attribute.GetCustomAttribute(member, typeof(ParseAttribute));

            return(parseAttribute == null ? null : parseAttribute.DefaultParameters);
        }
        /// <summary>
        /// Get Parse Type Or Null.
        /// </summary>
        /// <param name="member">The Member.</param>
        /// <returns>Type of Parse.</returns>
        public static Type GetParseTypeOrNull(this MemberInfo member)
        {
            ParseAttribute parseAttribute = (ParseAttribute)Attribute.GetCustomAttribute(member, typeof(ParseAttribute));

            return(parseAttribute == null ? null : parseAttribute.ParseTypeOrNull);
        }