private void WriteStructMethod(StructMapping mapping)
{
string methodName = (string)MethodNames[mapping];
ilg = new CodeGenerator(this.typeBuilder);
List<Type> argTypes = new List<Type>(5);
List<string> argNames = new List<string>(5);
argTypes.Add(typeof(string));
argNames.Add("n");
argTypes.Add(typeof(string));
argNames.Add("ns");
argTypes.Add(mapping.TypeDesc.Type);
argNames.Add("o");
if (mapping.TypeDesc.IsNullable)
{
argTypes.Add(typeof(Boolean));
argNames.Add("isNullable");
}
argTypes.Add(typeof(Boolean));
argNames.Add("needType");
ilg.BeginMethod(typeof(void),
GetMethodBuilder(methodName),
argTypes.ToArray(),
argNames.ToArray(),
CodeGenerator.PrivateMethodAttributes);
if (mapping.TypeDesc.IsNullable)
{
ilg.If(ilg.GetArg("o"), Cmp.EqualTo, null);
{
ilg.If(ilg.GetArg("isNullable"), Cmp.EqualTo, true);
{
MethodInfo XmlSerializationWriter_WriteNullTagLiteral = typeof(XmlSerializationWriter).GetMethod(
"WriteNullTagLiteral",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(String), typeof(String) }
);
ilg.Ldarg(0);
ilg.Ldarg("n");
ilg.Ldarg("ns");
ilg.Call(XmlSerializationWriter_WriteNullTagLiteral);
}
ilg.EndIf();
ilg.GotoMethodEnd();
}
ilg.EndIf();
}
ilg.If(ilg.GetArg("needType"), Cmp.NotEqualTo, true); // if (!needType)
LocalBuilder tLoc = ilg.DeclareLocal(typeof(Type), "t");
MethodInfo Object_GetType = typeof(object).GetMethod(
"GetType",
CodeGenerator.InstanceBindingFlags,
Array.Empty<Type>()
);
ArgBuilder oArg = ilg.GetArg("o");
ilg.LdargAddress(oArg);
ilg.ConvertAddress(oArg.ArgType, typeof(object));
ilg.Call(Object_GetType);
ilg.Stloc(tLoc);
WriteTypeCompare("t", mapping.TypeDesc.Type);
// Bool on the stack from WriteTypeCompare.
ilg.If(); // if (t == typeof(...))
WriteDerivedTypes(mapping);
if (mapping.TypeDesc.IsRoot)
WriteEnumAndArrayTypes();
ilg.Else();
if (mapping.TypeDesc.IsRoot)
{
MethodInfo XmlSerializationWriter_WriteTypedPrimitive = typeof(XmlSerializationWriter).GetMethod(
"WriteTypedPrimitive",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(String), typeof(String), typeof(Object), typeof(Boolean) }
);
ilg.Ldarg(0);
ilg.Ldarg("n");
ilg.Ldarg("ns");
ilg.Ldarg("o");
ilg.Ldc(true);
ilg.Call(XmlSerializationWriter_WriteTypedPrimitive);
ilg.GotoMethodEnd();
}
else
{
MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod(
"CreateUnknownTypeException",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(Object) }
);
ilg.Ldarg(0);
ilg.Ldarg(oArg);
ilg.ConvertValue(oArg.ArgType, typeof(Object));
ilg.Call(XmlSerializationWriter_CreateUnknownTypeException);
ilg.Throw();
}
ilg.EndIf(); // if (t == typeof(...))
ilg.EndIf(); // if (!needType)
if (!mapping.TypeDesc.IsAbstract)
{
if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type))
{
MethodInfo XmlSerializationWriter_set_EscapeName = typeof(XmlSerializationWriter).GetMethod(
"set_EscapeName",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(Boolean) }
);
ilg.Ldarg(0);
ilg.Ldc(false);
ilg.Call(XmlSerializationWriter_set_EscapeName);
}
string xmlnsSource = null;
MemberMapping[] members = TypeScope.GetAllMembers(mapping, memberInfos);
int xmlnsMember = FindXmlnsIndex(members);
if (xmlnsMember >= 0)
{
MemberMapping member = members[xmlnsMember];
CodeIdentifier.CheckValidIdentifier(member.Name);
xmlnsSource = RaCodeGen.GetStringForMember("o", member.Name, mapping.TypeDesc);
}
ilg.Ldarg(0);
ilg.Ldarg("n");
ilg.Ldarg("ns");
ArgBuilder argO = ilg.GetArg("o");
ilg.Ldarg(argO);
ilg.ConvertValue(argO.ArgType, typeof(Object));
ilg.Ldc(false);
if (xmlnsSource == null)
ilg.Load(null);
else
{
System.Diagnostics.Debug.Assert(xmlnsSource.StartsWith("o.@", StringComparison.Ordinal));
ILGenLoad(xmlnsSource);
}
MethodInfo XmlSerializationWriter_WriteStartElement = typeof(XmlSerializationWriter).GetMethod(
"WriteStartElement",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(String), typeof(String), typeof(Object), typeof(Boolean), typeof(XmlSerializerNamespaces) }
);
ilg.Call(XmlSerializationWriter_WriteStartElement);
if (!mapping.TypeDesc.IsRoot)
{
ilg.If(ilg.GetArg("needType"), Cmp.EqualTo, true);
{
MethodInfo XmlSerializationWriter_WriteXsiType = typeof(XmlSerializationWriter).GetMethod(
"WriteXsiType",
CodeGenerator.InstanceBindingFlags,
new Type[] { typeof(String), typeof(String) }
);
ilg.Ldarg(0);
ilg.Ldstr(GetCSharpString(mapping.TypeName));
ilg.Ldstr(GetCSharpString(mapping.Namespace));
ilg.Call(XmlSerializationWriter_WriteXsiType);
}
ilg.EndIf();
}
for (int i = 0; i < members.Length; i++)
{
MemberMapping m = members[i];
if (m.Attribute != null)
{
CodeIdentifier.CheckValidIdentifier(m.Name);
if (m.CheckShouldPersist)
{
ilg.LdargAddress(oArg);
ilg.Call(m.CheckShouldPersistMethodInfo);
ilg.If();
}
if (m.CheckSpecified != SpecifiedAccessor.None)
{
string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc);
ILGenLoad(memberGet);
ilg.If();
}
WriteMember(RaCodeGen.GetSourceForMember("o", m, mapping.TypeDesc, ilg), m.Attribute, m.TypeDesc, "o");
if (m.CheckSpecified != SpecifiedAccessor.None)
{
ilg.EndIf();
}
if (m.CheckShouldPersist)
{
ilg.EndIf();
}
}
}
for (int i = 0; i < members.Length; i++)
{
MemberMapping m = members[i];
if (m.Xmlns != null)
continue;
CodeIdentifier.CheckValidIdentifier(m.Name);
bool checkShouldPersist = m.CheckShouldPersist && (m.Elements.Length > 0 || m.Text != null);
if (checkShouldPersist)
{
ilg.LdargAddress(oArg);
ilg.Call(m.CheckShouldPersistMethodInfo);
ilg.If();
}
if (m.CheckSpecified != SpecifiedAccessor.None)
{
string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc);
ILGenLoad(memberGet);
ilg.If();
}
string choiceSource = null;
if (m.ChoiceIdentifier != null)
{
CodeIdentifier.CheckValidIdentifier(m.ChoiceIdentifier.MemberName);
choiceSource = RaCodeGen.GetStringForMember("o", m.ChoiceIdentifier.MemberName, mapping.TypeDesc);
}
WriteMember(RaCodeGen.GetSourceForMember("o", m, m.MemberInfo, mapping.TypeDesc, ilg), choiceSource, m.ElementsSortedByDerivation, m.Text, m.ChoiceIdentifier, m.TypeDesc, true);
if (m.CheckSpecified != SpecifiedAccessor.None)
{
ilg.EndIf();
}
if (checkShouldPersist)
{
ilg.EndIf();
}
}
WriteEndElement("o");
}
ilg.EndMethod();
}