private MemberMapping ImportChoiceGroup(XmlSchemaGroupBase group, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, bool groupRepeats, ref bool needExplicitOrder, bool allowDuplicates)
{
NameTable choiceElements = new NameTable();
if (GatherGroupChoices(group, choiceElements, identifier, ns, ref needExplicitOrder, allowDuplicates))
groupRepeats = true;
MemberMapping member = new MemberMapping();
member.Elements = (ElementAccessor[])choiceElements.ToArray(typeof(ElementAccessor));
Array.Sort(member.Elements, new ElementComparer());
AddScopeElements(elementsScope, member.Elements, ref needExplicitOrder, allowDuplicates);
bool duplicateTypes = false;
bool nullableMismatch = false;
Hashtable uniqueTypeDescs = new Hashtable(member.Elements.Length);
for (int i = 0; i < member.Elements.Length; i++)
{
ElementAccessor element = member.Elements[i];
string tdFullName = element.Mapping.TypeDesc.FullName;
object val = uniqueTypeDescs[tdFullName];
if (val != null)
{
duplicateTypes = true;
ElementAccessor existingElement = (ElementAccessor)val;
if (!nullableMismatch && existingElement.IsNullable != element.IsNullable)
nullableMismatch = true;
}
else
{
uniqueTypeDescs.Add(tdFullName, element);
}
ArrayMapping arrayMapping = element.Mapping as ArrayMapping;
if (arrayMapping != null)
{
if (IsNeedXmlSerializationAttributes(arrayMapping))
{
// we cannot use ArrayMapping in choice if additional custom
// serialization attributes are needed to serialize it
element.Mapping = arrayMapping.TopLevelMapping;
element.Mapping.ReferencedByTopLevelElement = false;
element.Mapping.ReferencedByElement = true;
}
}
}
if (nullableMismatch)
member.TypeDesc = Scope.GetTypeDesc(typeof(object));
else
{
TypeDesc[] typeDescs = new TypeDesc[uniqueTypeDescs.Count];
IEnumerator enumerator = uniqueTypeDescs.Values.GetEnumerator();
for (int i = 0; i < typeDescs.Length; i++)
{
if (!enumerator.MoveNext())
break;
typeDescs[i] = ((ElementAccessor)enumerator.Current).Mapping.TypeDesc;
}
member.TypeDesc = TypeDesc.FindCommonBaseTypeDesc(typeDescs);
if (member.TypeDesc == null) member.TypeDesc = Scope.GetTypeDesc(typeof(object));
}
if (groupRepeats)
member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc();
if (membersScope != null)
{
member.Name = membersScope.AddUnique(groupRepeats ? "Items" : "Item", member);
if (members != null)
{
members.Add(member.Name, member);
}
}
if (duplicateTypes)
{
member.ChoiceIdentifier = new ChoiceIdentifierAccessor();
member.ChoiceIdentifier.MemberName = member.Name + "ElementName";
// we need to create the EnumMapping to store all of the element names
member.ChoiceIdentifier.Mapping = ImportEnumeratedChoice(member.Elements, ns, member.Name + "ChoiceType");
member.ChoiceIdentifier.MemberIds = new string[member.Elements.Length];
ConstantMapping[] constants = ((EnumMapping)member.ChoiceIdentifier.Mapping).Constants;
for (int i = 0; i < member.Elements.Length; i++)
{
member.ChoiceIdentifier.MemberIds[i] = constants[i].Name;
}
MemberMapping choiceIdentifier = new MemberMapping();
choiceIdentifier.Ignore = true;
choiceIdentifier.Name = member.ChoiceIdentifier.MemberName;
if (groupRepeats)
{
choiceIdentifier.TypeDesc = member.ChoiceIdentifier.Mapping.TypeDesc.CreateArrayTypeDesc();
}
else
{
choiceIdentifier.TypeDesc = member.ChoiceIdentifier.Mapping.TypeDesc;
}
// create element accessor for the choiceIdentifier
ElementAccessor choiceAccessor = new ElementAccessor();
choiceAccessor.Name = choiceIdentifier.Name;
choiceAccessor.Namespace = ns;
choiceAccessor.Mapping = member.ChoiceIdentifier.Mapping;
choiceIdentifier.Elements = new ElementAccessor[] { choiceAccessor };
if (membersScope != null)
{
choiceAccessor.Name = choiceIdentifier.Name = member.ChoiceIdentifier.MemberName = membersScope.AddUnique(member.ChoiceIdentifier.MemberName, choiceIdentifier);
if (members != null)
{
members.Add(choiceAccessor.Name, choiceIdentifier);
}
}
}
return member;
}