in src/dotnet-svcutil/lib/src/FrameworkFork/Microsoft.Xml/Xml/Serialization/XmlSerializationWriterILGen.cs [1648:1951]
private void WriteElements(SourceInfo source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable)
{
if (elements.Length == 0 && text == null) return;
if (elements.Length == 1 && text == null)
{
TypeDesc td = elements[0].IsUnbounded ? elements[0].Mapping.TypeDesc.CreateArrayTypeDesc() : elements[0].Mapping.TypeDesc;
if (!elements[0].Any && !elements[0].Mapping.TypeDesc.IsOptionalValue)
source = source.CastTo(td);
WriteElement(source, elements[0], arrayName, writeAccessors);
}
else
{
bool doEndIf = false;
if (isNullable && choice == null)
{
source.Load(typeof(object));
ilg.Load(null);
ilg.If(Cmp.NotEqualTo);
doEndIf = true;
}
int anyCount = 0;
ArrayList namedAnys = new ArrayList();
ElementAccessor unnamedAny = null; // can only have one
bool wroteFirstIf = false;
string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName;
for (int i = 0; i < elements.Length; i++)
{
ElementAccessor element = elements[i];
if (element.Any)
{
anyCount++;
if (element.Name != null && element.Name.Length > 0)
namedAnys.Add(element);
else if (unnamedAny == null)
unnamedAny = element;
}
else if (choice != null)
{
string fullTypeName = element.Mapping.TypeDesc.CSharpName;
object enumValue;
string enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue);
if (wroteFirstIf) ilg.InitElseIf();
else { wroteFirstIf = true; ilg.InitIf(); }
ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type);
ilg.Load(enumValue);
ilg.Ceq();
if (isNullable && !element.IsNullable)
{
Label labelFalse = ilg.DefineLabel();
Label labelEnd = ilg.DefineLabel();
ilg.Brfalse(labelFalse);
source.Load(typeof(object));
ilg.Load(null);
ilg.Cne();
ilg.Br_S(labelEnd);
ilg.MarkLabel(labelFalse);
ilg.Ldc(false);
ilg.MarkLabel(labelEnd);
}
ilg.AndIf();
WriteChoiceTypeCheck(source, fullTypeName, choice, enumFullName, element.Mapping.TypeDesc);
SourceInfo castedSource = source;
castedSource = source.CastTo(element.Mapping.TypeDesc);
WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors);
}
else
{
TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc;
string fullTypeName = td.CSharpName;
if (wroteFirstIf) ilg.InitElseIf();
else { wroteFirstIf = true; ilg.InitIf(); }
WriteInstanceOf(source, td.Type);
// WriteInstanceOf leave bool on the stack
ilg.AndIf();
SourceInfo castedSource = source;
castedSource = source.CastTo(td);
WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors);
}
}
if (wroteFirstIf)
{
if (anyCount > 0)
{
// See "else " below
if (elements.Length - anyCount > 0)
{ // NOOP
}
else ilg.EndIf();
}
}
if (anyCount > 0)
{
if (elements.Length - anyCount > 0) ilg.InitElseIf();
else ilg.InitIf();
string fullTypeName = typeof(XmlElement).FullName;
source.Load(typeof(object));
ilg.IsInst(typeof(XmlElement));
ilg.Load(null);
ilg.Cne();
ilg.AndIf();
LocalBuilder elemLoc = ilg.DeclareLocal(typeof(XmlElement), "elem");
source.Load(typeof(XmlElement));
ilg.Stloc(elemLoc);
int c = 0;
foreach (ElementAccessor element in namedAnys)
{
if (c++ > 0) ilg.InitElseIf();
else ilg.InitIf();
string enumFullName = null;
Label labelEnd, labelFalse;
if (choice != null)
{
object enumValue;
enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue);
labelFalse = ilg.DefineLabel();
labelEnd = ilg.DefineLabel();
ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type);
ilg.Load(enumValue);
ilg.Bne(labelFalse);
if (isNullable && !element.IsNullable)
{
source.Load(typeof(object));
ilg.Load(null);
ilg.Cne();
}
else
{
ilg.Ldc(true);
}
ilg.Br(labelEnd);
ilg.MarkLabel(labelFalse);
ilg.Ldc(false);
ilg.MarkLabel(labelEnd);
ilg.AndIf();
}
labelFalse = ilg.DefineLabel();
labelEnd = ilg.DefineLabel();
MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod(
"get_Name",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod(
"get_NamespaceURI",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldloc(elemLoc);
ilg.Call(XmlNode_get_Name);
ilg.Ldstr(element.Name);
MethodInfo String_op_Equality = typeof(string).GetMethod(
"op_Equality",
CodeGenerator.StaticBindingFlags,
null,
new Type[] { typeof(string), typeof(string) },
null
);
ilg.Call(String_op_Equality);
ilg.Brfalse(labelFalse);
ilg.Ldloc(elemLoc);
ilg.Call(XmlNode_get_NamespaceURI);
ilg.Ldstr(element.Namespace);
ilg.Call(String_op_Equality);
ilg.Br(labelEnd);
ilg.MarkLabel(labelFalse);
ilg.Ldc(false);
ilg.MarkLabel(labelEnd);
if (choice != null) ilg.If();
else ilg.AndIf();
WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), element, arrayName, writeAccessors);
if (choice != null)
{
ilg.Else();
MethodInfo XmlSerializationWriter_CreateChoiceIdentifierValueException = typeof(XmlSerializationWriter).GetMethod(
"CreateChoiceIdentifierValueException",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(String), typeof(String), typeof(String), typeof(String) },
null
);
ilg.Ldarg(0);
ilg.Ldstr(enumFullName);
ilg.Ldstr(choice.MemberName);
ilg.Ldloc(elemLoc);
ilg.Call(XmlNode_get_Name);
ilg.Ldloc(elemLoc);
ilg.Call(XmlNode_get_NamespaceURI);
ilg.Call(XmlSerializationWriter_CreateChoiceIdentifierValueException);
ilg.Throw();
ilg.EndIf();
}
}
if (c > 0)
{
ilg.Else();
}
if (unnamedAny != null)
{
WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), unnamedAny, arrayName, writeAccessors);
}
else
{
MethodInfo XmlSerializationWriter_CreateUnknownAnyElementException = typeof(XmlSerializationWriter).GetMethod(
"CreateUnknownAnyElementException",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(String), typeof(String) },
null
);
ilg.Ldarg(0);
ilg.Ldloc(elemLoc);
MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod(
"get_Name",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod(
"get_NamespaceURI",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Call(XmlNode_get_Name);
ilg.Ldloc(elemLoc);
ilg.Call(XmlNode_get_NamespaceURI);
ilg.Call(XmlSerializationWriter_CreateUnknownAnyElementException);
ilg.Throw();
}
if (c > 0)
{
ilg.EndIf();
}
}
if (text != null)
{
string fullTypeName = text.Mapping.TypeDesc.CSharpName;
if (elements.Length > 0)
{
ilg.InitElseIf();
WriteInstanceOf(source, text.Mapping.TypeDesc.Type);
ilg.AndIf();
SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc);
WriteText(castedSource, text);
}
else
{
SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc);
WriteText(castedSource, text);
}
}
if (elements.Length > 0)
{
if (isNullable)
{
ilg.InitElseIf();
source.Load(null);
ilg.Load(null);
ilg.AndIf(Cmp.NotEqualTo);
}
else
{
ilg.Else();
}
MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod(
"CreateUnknownTypeException",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(Object) },
null
);
ilg.Ldarg(0);
source.Load(typeof(object));
ilg.Call(XmlSerializationWriter_CreateUnknownTypeException);
ilg.Throw();
ilg.EndIf();
}
// See ilg.If() cond above
if (doEndIf) // if (isNullable && choice == null)
ilg.EndIf();
}
}