StructMapping ImportStructLikeMapping(StructModel model, string ns, bool openModel, XmlAttributes a) {
if (model.TypeDesc.Kind == TypeKind.Root) return GetRootMapping();
if (a == null)
a = GetAttributes(model.Type, false);
string typeNs = ns;
if (a.XmlType != null && a.XmlType.Namespace != null)
typeNs = a.XmlType.Namespace;
else if (a.XmlRoot != null && a.XmlRoot.Namespace != null)
typeNs = a.XmlRoot.Namespace;
string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name);
typeName = XmlConvert.EncodeLocalName(typeName);
StructMapping mapping = (StructMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc, types, model.Type);
if (mapping == null) {
mapping = new StructMapping();
mapping.TypeDesc = model.TypeDesc;
mapping.Namespace = typeNs;
mapping.TypeName = typeName;
if (!mapping.IsAnonymousType)
types.Add(typeName, typeNs, mapping);
else
anonymous[model.Type] = mapping;
if (a.XmlType != null) {
mapping.IncludeInSchema = a.XmlType.IncludeInSchema;
}
if (model.TypeDesc.BaseTypeDesc != null) {
TypeModel baseModel = modelScope.GetTypeModel(model.Type.BaseType, false);
if (!(baseModel is StructModel)) {
//XmlUnsupportedInheritance=Using '{0}' as a base type for a class is not supported by XmlSerializer.
throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedInheritance, model.Type.BaseType.FullName));
}
mapping.BaseMapping = ImportStructLikeMapping((StructModel)baseModel, mapping.Namespace, openModel, null);
ICollection values = mapping.BaseMapping.LocalAttributes.Values;
foreach (AttributeAccessor attribute in values) {
AddUniqueAccessor(mapping.LocalAttributes, attribute);
}
if (!mapping.BaseMapping.HasExplicitSequence()) {
values = mapping.BaseMapping.LocalElements.Values;
foreach (ElementAccessor e in values) {
AddUniqueAccessor(mapping.LocalElements, e);
}
}
}
ArrayList members = new ArrayList();
TextAccessor textAccesor = null;
bool hasElements = false;
bool isSequence = false;
foreach (MemberInfo memberInfo in model.GetMemberInfos()) {
if ((memberInfo.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0)
continue;
XmlAttributes memberAttrs = GetAttributes(memberInfo);
if (memberAttrs.XmlIgnore) continue;
FieldModel fieldModel = model.GetFieldModel(memberInfo);
if (fieldModel == null) continue;
try {
MemberMapping member = ImportFieldMapping(model, fieldModel, memberAttrs, mapping.Namespace);
if (member == null) continue;
if (mapping.BaseMapping != null) {
if (mapping.BaseMapping.Declares(member, mapping.TypeName)) continue;
}
isSequence |= member.IsSequence;
// add All memeber accessors to the scope accessors
AddUniqueAccessor(member, mapping.LocalElements, mapping.LocalAttributes, isSequence);
if (member.Text != null) {
if (!member.Text.Mapping.TypeDesc.CanBeTextValue && member.Text.Mapping.IsList)
throw new InvalidOperationException(Res.GetString(Res.XmlIllegalTypedTextAttribute, typeName, member.Text.Name, member.Text.Mapping.TypeDesc.FullName));
if (textAccesor != null) {
throw new InvalidOperationException(Res.GetString(Res.XmlIllegalMultipleText, model.Type.FullName));
}
textAccesor = member.Text;
}
if (member.Xmlns != null) {
if (mapping.XmlnsMember != null)
throw new InvalidOperationException(Res.GetString(Res.XmlMultipleXmlns, model.Type.FullName));
mapping.XmlnsMember = member;
}
if (member.Elements != null && member.Elements.Length != 0) {
hasElements = true;
}
members.Add(member);
}
catch (Exception e) {
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
throw;
}
throw CreateMemberReflectionException(fieldModel, e);
}
catch {
throw CreateMemberReflectionException(fieldModel, null);
}
}
mapping.SetContentModel(textAccesor, hasElements);
if (isSequence) {
Hashtable ids = new Hashtable();
for (int i = 0; i < members.Count; i++) {
MemberMapping member = (MemberMapping)members[i];
if (!member.IsParticle)
continue;
if (member.IsSequence) {
if (ids[member.SequenceId] != null) {
throw new InvalidOperationException(Res.GetString(Res.XmlSequenceUnique, member.SequenceId.ToString(CultureInfo.InvariantCulture), "Order", member.Name));
}
ids[member.SequenceId] = member;
}
else {
throw new InvalidOperationException(Res.GetString(Res.XmlSequenceInconsistent, "Order", member.Name));
}
}
members.Sort(new MemberMappingComparer());
}
mapping.Members = (MemberMapping[])members.ToArray(typeof(MemberMapping));
if (mapping.BaseMapping == null) mapping.BaseMapping = GetRootMapping();
if (mapping.XmlnsMember != null && mapping.BaseMapping.HasXmlnsMember)
throw new InvalidOperationException(Res.GetString(Res.XmlMultipleXmlns, model.Type.FullName));
IncludeTypes(model.Type);
typeScope.AddTypeMapping(mapping);
}
if (openModel)
mapping.IsOpenModel = true;
return mapping;
}