private void ParseComplexTypeForAttributes(XmlSchemaComplexType complexType, XSDMessage Message)
        {
            foreach (XmlSchemaAttribute a in complexType.Attributes)
            {
                XmlSchemaSimpleType st = a.AttributeSchemaType;
                if (st != null && Message.ContainsKey(a.Name))
                {
                    SetSchemaFacets(st, Message[a.Name]);
                }
            }

            XmlSchemaSequence sequence = complexType.Particle as XmlSchemaSequence;

            if (sequence != null)
            {
                foreach (XmlSchemaElement sequenceItem in sequence.Items)
                {
                    XmlSchemaComplexType sequenceItemComplexType = sequenceItem.ElementSchemaType as XmlSchemaComplexType;
                    if (sequenceItemComplexType != null)
                    {
                        ParseComplexTypeForAttributes(sequenceItemComplexType, Message);
                    }

                    XmlSchemaSimpleType sequenceItemSimpleType = sequenceItem.ElementSchemaType as XmlSchemaSimpleType;
                    if (sequenceItemSimpleType != null)
                    {
                        if (Message.ContainsKey(sequenceItem.Name))
                        {
                            XmlSchemaSimpleType newType = SetSchemaFacets(sequenceItemSimpleType, Message[sequenceItem.Name]);

                            sequenceItem.SchemaType     = newType;
                            sequenceItem.SchemaTypeName = new XmlQualifiedName();
                        }
                    }

                    SetMinOccurs(sequenceItem, Message[sequenceItem.Name]);
                }
            }
        }
        void ExtractAttributes(PropertyInfo pi, MessageDescription Message, OperationDescription Operation, MessagePartDescription MessagePartDescription)
        {
            object[] xmlElementAttributes   = pi.GetCustomAttributes(typeof(XmlElementAttribute), false);
            object[] stringLengthAttributes = pi.GetCustomAttributes(typeof(StringLengthAttribute), false);
            object[] regexAttributes        = pi.GetCustomAttributes(typeof(RegularExpressionAttribute), false);
            object[] rangeAttributes        = pi.GetCustomAttributes(typeof(RangeAttribute), false);
            object[] dataMemberAttributes   = pi.GetCustomAttributes(typeof(DataMemberAttribute), false);

            string ElemName = pi.Name;

            //pick up XmlElement's ElementName if used to match later
            if (xmlElementAttributes.Length > 0)
            {
                XmlElementAttribute xmlElementAttrib = xmlElementAttributes[0] as XmlElementAttribute;
                if (!string.IsNullOrWhiteSpace(xmlElementAttrib.ElementName))
                {
                    ElemName = xmlElementAttrib.ElementName;
                }
            }
            if (!_Namespaces.ContainsKey(MessagePartDescription.Namespace))
            {
                _Namespaces.Add(MessagePartDescription.Namespace, new XSDNamespace());
            }

            XSDNamespace Namespace = _Namespaces[MessagePartDescription.Namespace];

            if (!Namespace.ContainsKey(Operation.Name))
            {
                Namespace.Add(Operation.Name, new XSDMessage());
            }

            XSDMessage XsdMessage = Namespace[Operation.Name];

            for (int i = 0; i < stringLengthAttributes.Length; i++)
            {
                StringLengthAttribute sla = stringLengthAttributes[i] as StringLengthAttribute;

                XsdMessage.Add(ElemName, new StringLengthMessagePart()
                {
                    MinLength = sla.MinimumLength,
                    MaxLength = sla.MaximumLength
                });
            }

            for (int i = 0; i < regexAttributes.Length; i++)
            {
                RegularExpressionAttribute rea = regexAttributes[i] as RegularExpressionAttribute;

                XsdMessage.Add(ElemName, new RegexMessagePart()
                {
                    Regex = rea.Pattern
                });
            }

            for (int i = 0; i < rangeAttributes.Length; i++)
            {
                RangeAttribute raa = rangeAttributes[i] as RangeAttribute;

                XsdMessage.Add(ElemName, new RangeMessagePart()
                {
                    Min = raa.Minimum,
                    Max = raa.Maximum
                });
            }
            for (int i = 0; i < dataMemberAttributes.Length; i++)
            {
                DataMemberAttribute dma = dataMemberAttributes[i] as DataMemberAttribute;

                XsdMessage.Add(ElemName, new RequiredMessagePart()
                {
                    Required = dma.IsRequired
                });
            }

            //rough seach for properties that are "custom" classes: there isn't a better way of doing it that I can find.
            if (pi.PropertyType.IsClass && (pi.PropertyType.BaseType != pi.PropertyType) && !pi.PropertyType.Namespace.StartsWith("System.") && !pi.PropertyType.Namespace.StartsWith("Microsoft."))     //hopefully filter out base objects
            {
                //iterate nested properties, looking for more attributes
                foreach (PropertyInfo piNested in pi.PropertyType.GetProperties())
                {
                    ExtractAttributes(piNested, Message, Operation, MessagePartDescription);
                }
            }
        }