private bool InitializeStructMembers(StructMapping mapping, StructModel model, bool openModel, string typeName, RecursionLimiter limiter)
{
if (mapping.IsFullyInitialized)
return true;
if (model.TypeDesc.BaseTypeDesc != null)
{
TypeModel baseModel = _modelScope.GetTypeModel(model.Type.GetTypeInfo().BaseType, false);
if (!(baseModel is StructModel))
{
//XmlUnsupportedInheritance=Using '{0}' as a base type for a class is not supported by XmlSerializer.
throw new NotSupportedException(SR.Format(SR.XmlUnsupportedInheritance, model.Type.GetTypeInfo().BaseType.FullName));
}
StructMapping baseMapping = ImportStructLikeMapping((StructModel)baseModel, mapping.Namespace, openModel, null, limiter);
// check to see if the import of the baseMapping was deffered
int baseIndex = limiter.DeferredWorkItems.IndexOf(baseMapping);
if (baseIndex < 0)
{
mapping.BaseMapping = baseMapping;
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);
}
}
}
else
{
// the import of the baseMapping was deffered, make sure that the derived mappings is deffered as well
if (!limiter.DeferredWorkItems.Contains(mapping))
{
limiter.DeferredWorkItems.Add(new ImportStructWorkItem(model, mapping));
}
// make sure that baseMapping get processed before the derived
int top = limiter.DeferredWorkItems.Count - 1;
if (baseIndex < top)
{
ImportStructWorkItem baseMappingWorkItem = limiter.DeferredWorkItems[baseIndex];
limiter.DeferredWorkItems[baseIndex] = limiter.DeferredWorkItems[top];
limiter.DeferredWorkItems[top] = baseMappingWorkItem;
}
return false;
}
}
ArrayList members = new ArrayList();
TextAccessor textAccesor = null;
bool hasElements = false;
bool isSequence = false;
foreach (MemberInfo memberInfo in model.GetMemberInfos())
{
if (!(memberInfo is FieldInfo || memberInfo is PropertyInfo))
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, limiter);
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(SR.Format(SR.XmlIllegalTypedTextAttribute, typeName, member.Text.Name, member.Text.Mapping.TypeDesc.FullName));
if (textAccesor != null)
{
throw new InvalidOperationException(SR.Format(SR.XmlIllegalMultipleText, model.Type.FullName));
}
textAccesor = member.Text;
}
if (member.Xmlns != null)
{
if (mapping.XmlnsMember != null)
throw new InvalidOperationException(SR.Format(SR.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 OutOfMemoryException)
{
throw;
}
throw CreateMemberReflectionException(fieldModel, e);
}
}
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(SR.Format(SR.XmlSequenceUnique, member.SequenceId.ToString(CultureInfo.InvariantCulture), "Order", member.Name));
}
ids[member.SequenceId] = member;
}
else
{
throw new InvalidOperationException(SR.Format(SR.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(SR.Format(SR.XmlMultipleXmlns, model.Type.FullName));
IncludeTypes(model.Type.GetTypeInfo(), limiter);
_typeScope.AddTypeMapping(mapping);
if (openModel)
mapping.IsOpenModel = true;
return true;
}