/// <summary>
        /// Reflects over all the public events on the type and adds EventDefinitions to the class defintion
        /// </summary>
        /// <param name="parsertype"></param>
        /// <param name="defn"></param>
        private static void LoadClassEvents(Type parsertype, ParserClassDefinition defn)
        {
            EventInfo[] all = parsertype.GetEvents(BindingFlags.Public | BindingFlags.Instance);

            foreach (EventInfo ei in all)
            {
                PDFParserIgnoreAttribute ignore = GetCustomAttribute <PDFParserIgnoreAttribute>(ei, true);
                if (null != ignore && ignore.Ignore)
                {
                    continue; //Ignore the event
                }
                PDFAttributeAttribute attr = GetCustomAttribute <PDFAttributeAttribute>(ei, true);
                if (null != attr)
                {
                    string name = attr.AttributeName;
                    if (string.IsNullOrEmpty(name))
                    {
                        throw new PDFParserException(String.Format(Errors.ParserAttributeNameCannotBeEmpty, ei.Name, parsertype.FullName));
                    }


                    ParserEventDefinition evt = new ParserEventDefinition(name, ei);
                    defn.Events.Add(evt);
                }
            }
        }
        /// <summary>
        /// Loads all the properties and methods on the specified type into a full ParserClassDefinition
        /// </summary>
        /// <param name="parsertype"></param>
        /// <returns></returns>
        private static ParserClassDefinition LoadClassDefinition(Type parsertype)
        {
            ParserClassDefinition defn = new ParserClassDefinition(parsertype);

            LoadClassAttributes(parsertype, defn);
            LoadClassProperties(parsertype, defn);
            LoadClassEvents(parsertype, defn);
            return(defn);
        }
        /// <summary>
        /// Loads the class attributes for the type
        /// </summary>
        /// <param name="parsertype"></param>
        /// <param name="defn"></param>
        private static void LoadClassAttributes(Type parsertype, ParserClassDefinition defn)
        {
            PDFRequiredFrameworkAttribute req = GetCustomAttribute <PDFRequiredFrameworkAttribute>(parsertype, true);

            if (null != req)
            {
                if (req.Minimum != PDFRequiredFrameworkAttribute.Empty)
                {
                    if (defn.MinRequiredFramework == PDFRequiredFrameworkAttribute.Empty)
                    {
                        defn.MinRequiredFramework = req.Minimum;
                    }
                    else if (req.Minimum > defn.MinRequiredFramework)
                    {
                        defn.MinRequiredFramework = req.Minimum;
                    }
                }
                if (req.Maximum != PDFRequiredFrameworkAttribute.Empty)
                {
                    if (defn.MaxSupportedFramework == PDFRequiredFrameworkAttribute.Empty)
                    {
                        defn.MaxSupportedFramework = req.Maximum;
                    }
                    else if (req.Maximum < defn.MaxSupportedFramework)
                    {
                        defn.MaxSupportedFramework = req.Maximum;
                    }
                }
            }

            PDFRemoteParsableComponentAttribute remote = GetCustomAttribute <PDFRemoteParsableComponentAttribute>(parsertype, true);

            if (null != remote)
            {
                defn.SetRemoteParsable(true, remote.ElementName, remote.SourceAttribute);
            }
        }
        /// <summary>
        /// Reflects over all the public properties and adds them to the class definition
        /// </summary>
        /// <param name="parsertype"></param>
        /// <param name="defn"></param>
        private static void LoadClassProperties(Type parsertype, ParserClassDefinition defn)
        {
            PropertyInfo[] all = parsertype.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo pi in all)
            {
                PDFXmlConverter convert;
                string          name;
                string          ns       = string.Empty;
                bool            bindOnly = false;

                PDFParserIgnoreAttribute ignore = GetCustomAttribute <PDFParserIgnoreAttribute>(pi, true);
                if (null != ignore && ignore.Ignore)
                {
                    continue; //This property should be ignored.
                }
                PDFAttributeAttribute attr = GetCustomAttribute <PDFAttributeAttribute>(pi, true);

                if (null != attr)
                {
                    name = attr.AttributeName;
                    ns   = attr.AttributeNamespace;

                    bool iscustom = false;
                    if (string.IsNullOrEmpty(name))
                    {
                        throw new PDFParserException(String.Format(Errors.ParserAttributeNameCannotBeEmpty, pi.Name, parsertype.FullName));
                    }
                    if (IsReservedName(name))
                    {
                        throw new PDFParserException(String.Format(Errors.ReservedAttributeNameCannotBeUsed, name, pi.Name));
                    }

                    if (!IsKnownType(pi.PropertyType, out convert) && !IsCustomParsableType(pi.PropertyType, out convert, out iscustom))
                    {
                        if (!attr.BindingOnly)
                        {
                            throw new PDFParserException(String.Format(Errors.ParserAttributeMustBeSimpleOrCustomParsableType, pi.Name, parsertype.FullName, pi.PropertyType));
                        }
                        else
                        {
                            bindOnly = attr.BindingOnly;
                        }
                    }
                    ParserAttributeDefinition ad = new ParserAttributeDefinition(name, ns, pi, convert, iscustom, bindOnly);
                    CheckIsLoadedSource(ad, pi);

                    defn.Attributes.Add(ad);
                }

                PDFElementAttribute ele = GetCustomAttribute <PDFElementAttribute>(pi, true);
                if (null != ele)
                {
                    ParserPropertyDefinition propele;
                    bool isdefault = false;
                    name = ele.Name;
                    ns   = ele.NameSpace;

                    if (string.IsNullOrEmpty(name))
                    {
                        isdefault = true;
                    }
                    PDFArrayAttribute    array    = GetCustomAttribute <PDFArrayAttribute>(pi, true);
                    PDFTemplateAttribute template = GetCustomAttribute <PDFTemplateAttribute>(pi, true);
                    bool iscustom = false;

                    if (null != array)
                    {
                        Type basetype = array.ContentBaseType;
                        //ArrayCollection
                        if (null == basetype)
                        {
                            basetype = typeof(IPDFComponent);
                        }

                        propele = new ParserArrayDefinition(name, ns, basetype, pi);
                    }
                    else if (null != template)
                    {
                        propele = new ParserTemplateDefintion(name, pi);
                        if (template.IsBlock)
                        {
                            (propele as ParserTemplateDefintion).RenderAsBlock = true;
                        }
                    }
                    else if (IsKnownType(pi.PropertyType, out convert) || IsCustomParsableType(pi.PropertyType, out convert, out iscustom))
                    {
                        //SimpleElement
                        propele = new ParserSimpleElementDefinition(name, ns, pi, convert, iscustom);
                    }
                    else
                    {
                        //Complex Element
                        propele = new ParserComplexElementDefiniton(name, ns, pi);
                    }

                    CheckIsLoadedSource(propele, pi);

                    if (isdefault)
                    {
                        if (null != defn.DefaultElement)
                        {
                            throw new PDFParserException(String.Format(Errors.DuplicateDefaultElementOnClass, pi.Name, pi.DeclaringType));
                        }
                        else
                        {
                            defn.DefaultElement = propele;
                        }
                    }
                    else
                    {
                        defn.Elements.Add(propele);
                    }
                }
            }
        }