Abstract base class for classes that support serializing objects.
        /// <summary>
        /// Prescans the type.
        /// </summary>
        protected virtual void Scan(SerializerOptions options, bool includeIfUnattributed)
        {
            XmlApproachAttribute approach = null;
            XmlElementAttribute elementAttribute;

            // Get the applicable attributes

            LoadAttributes(options);

            // Get the setter/getter and serializer

            if (memberInfo is FieldInfo)
            {
                getterSetter = new FieldGetterSetter(memberInfo);

                returnType = ((FieldInfo) memberInfo).FieldType;
            }
            else if (memberInfo is PropertyInfo)
            {
                var propertyInfo = (PropertyInfo) memberInfo;

                getterSetter = new PropertyGetterSetter(memberInfo);

                returnType = ((PropertyInfo) memberInfo).PropertyType;
            }
            else if (memberInfo is Type)
            {
                getterSetter = null;

                serializedName = memberInfo.Name;
                returnType = (Type) memberInfo;
            }
            else
            {
                throw new ArgumentException($"Unsupported member type: {this.memberInfo.MemberType.ToString()}");
            }

            // Get the [XmlExclude] [XmlAttribute] or [XmlElement] attribute

            var attribute = GetFirstApplicableAttribute(false, typeof (XmlExcludeAttribute),typeof(XmlTextAttribute), typeof (XmlAttributeAttribute), typeof (XmlElementAttribute));

            if (attribute != null)
            {
                if (attribute is XmlExcludeAttribute)
                {
                    // This member needs to be excluded

                    serializedNodeType = XmlNodeType.None;
                }
                else if (attribute is XmlTextAttribute)
                {
                    serializedNodeType = XmlNodeType.Text;
                }
                else if ((approach = attribute as XmlApproachAttribute) != null)
                {
                    ApproachAttribute = approach;

                    // This member needs to be included as an attribute or an element

                    serializedNodeType = approach is XmlElementAttribute ? XmlNodeType.Element : XmlNodeType.Attribute;

                    if (approach.Type != null)
                    {
                        returnType = approach.Type;
                    }

                    serializedName = approach.Name;
                    serializedNamespace = approach.Namespace;

                    if ((elementAttribute = approach as XmlElementAttribute) != null)
                    {
                        if (elementAttribute.SerializeAsValueNode)
                        {
                            serializeAsValueNodeAttributeName = elementAttribute.ValueNodeAttributeName;
                        }
                    }

                    if (approach.SerializeUnattribted)
                    {
                        this.includeIfUnattributed = true;
                    }

                    if (approach.SerializeIfNull)
                        this.serializeIfNull = true;
                }
            }
            else
            {
                if (includeIfUnattributed)
                {
                    serializedName = memberInfo.Name;

                    serializedNodeType = XmlNodeType.Element;
                }
                else
                {
                    serializedNodeType = XmlNodeType.None;
                }
            }

            if (serializedNodeType == XmlNodeType.None)
            {
                return;
            }

            // Check if the member should be serialized as CDATA

            attribute = GetFirstApplicableAttribute(typeof (XmlCDataAttribute));

            if (attribute != null)
            {
                serializeAsCData = ((XmlCDataAttribute) attribute).Enabled;
            }

            attribute = GetFirstApplicableAttribute(typeof (XmlVariableSubstitutionAttribute));

            if (attribute != null)
            {
                Substitutor = (IVariableSubstitutor) Activator.CreateInstance(((XmlVariableSubstitutionAttribute) attribute).SubstitutorType);
            }

            // Set the serialized (element or attribute) name to the name of the member if it hasn't already been set

            if (serializedName.Length == 0)
            {
                if (approach != null && approach.UseNameFromAttributedType && memberInfo.MemberType == MemberTypes.TypeInfo)
                {
                    serializedName = GetAttributeDeclaringType((Type) memberInfo, approach).Name;
                }
                else
                {
                    serializedName = this.memberInfo.Name.Left(PredicateUtils.ObjectEquals('`').Not());
                }
            }

            // Make the serialized (element or attribute) name lowercase if requested

            if (approach != null)
            {
                if (approach.MakeNameLowercase)
                {
                    serializedName = serializedName.ToLower();
                }
            }

            // Get the explicitly specified TypeSerializer if requested

            attribute = GetFirstApplicableAttribute(typeof (XmlTypeSerializerTypeAttribute));

            if (attribute != null)
            {
                if (((XmlTypeSerializerTypeAttribute) attribute).SerializerType != null)
                {
                    typeSerializer = typeSerializerCache.GetTypeSerializerBySerializerType(((XmlTypeSerializerTypeAttribute) attribute).SerializerType, this);

                    if (!returnType.IsAssignableFrom(typeSerializer.SupportedType))
                    {
                        throw new InvalidOperationException($"Explicitly specified serializer ({((XmlTypeSerializerTypeAttribute)attribute).SerializerType.Name}) doesn't support serializing of associated program element.");
                    }
                }
            }
            else
            {
                typeSerializer = typeSerializerCache.GetTypeSerializerBySupportedType(returnType, this);
            }

            // Check if the member should be treated as a null value if it is empty

            treatAsNullIfEmpty = HasApplicableAttribute(typeof (XmlTreatAsNullIfEmptyAttribute));

            // Check if the member's declared type is polymorphic

            var polymorphicTypeAttribute = (XmlPolymorphicTypeAttribute) GetFirstApplicableAttribute(typeof (XmlPolymorphicTypeAttribute));

            if (polymorphicTypeAttribute != null)
            {
                polymorphicTypeProvider = (IXmlDynamicTypeProvider) Activator.CreateInstance(polymorphicTypeAttribute.PolymorphicTypeProvider);
            }
        }
 public LightSerializationMember(SerializationMemberInfo memberInfo)
 {
     this.Getter = memberInfo.Getter;
     this.Setter = memberInfo.Setter;
     this.Serializer = memberInfo.Serializer;
     this.MemberInfo = memberInfo.MemberInfo;
     this.SerializedName = memberInfo.GetSerializedName();
     this.SerializeAsCData = memberInfo.SerializeAsCData;
     this.XmlTreatAsNullIfEmpty = memberInfo.HasApplicableAttribute(typeof(XmlTreatAsNullIfEmptyAttribute));
     this.LogicalType = memberInfo.LogicalType;
 }