void WriteLiteralStructMethod(StructMapping structMapping) {
string methodName = (string)MethodNames[structMapping];
string typeName = structMapping.TypeDesc.CSharpName;
ilg = new CodeGenerator(this.typeBuilder);
List<Type> argTypes = new List<Type>();
List<string> argNames = new List<string>();
if (structMapping.TypeDesc.IsNullable) {
argTypes.Add(typeof(Boolean));
argNames.Add("isNullable");
}
argTypes.Add(typeof(Boolean));
argNames.Add("checkType");
ilg.BeginMethod(
structMapping.TypeDesc.Type,
GetMethodBuilder(methodName),
argTypes.ToArray(),
argNames.ToArray(),
CodeGenerator.PrivateMethodAttributes);
LocalBuilder locXsiType = ilg.DeclareLocal(typeof(XmlQualifiedName), "xsiType");
LocalBuilder locIsNull = ilg.DeclareLocal(typeof(Boolean), "isNull");
MethodInfo XmlSerializationReader_GetXsiType = typeof(XmlSerializationReader).GetMethod(
"GetXsiType",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
MethodInfo XmlSerializationReader_ReadNull = typeof(XmlSerializationReader).GetMethod(
"ReadNull",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
Label labelTrue = ilg.DefineLabel();
Label labelEnd = ilg.DefineLabel();
ilg.Ldarg("checkType");
ilg.Brtrue(labelTrue);
ilg.Load(null);
ilg.Br_S(labelEnd);
ilg.MarkLabel(labelTrue);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_GetXsiType);
ilg.MarkLabel(labelEnd);
ilg.Stloc(locXsiType);
ilg.Ldc(false);
ilg.Stloc(locIsNull);
if (structMapping.TypeDesc.IsNullable) {
ilg.Ldarg("isNullable");
ilg.If();
{
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_ReadNull);
ilg.Stloc(locIsNull);
}
ilg.EndIf();
}
ilg.Ldarg("checkType");
ilg.If(); // if (checkType)
if (structMapping.TypeDesc.IsRoot) {
ilg.Ldloc(locIsNull);
ilg.If();
ilg.Ldloc(locXsiType);
ilg.Load(null);
ilg.If(Cmp.NotEqualTo);
MethodInfo XmlSerializationReader_ReadTypedNull = typeof(XmlSerializationReader).GetMethod(
"ReadTypedNull",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { locXsiType.LocalType },
null
);
ilg.Ldarg(0);
ilg.Ldloc(locXsiType);
ilg.Call(XmlSerializationReader_ReadTypedNull);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
ilg.Else();
if (structMapping.TypeDesc.IsValueType) {
throw CodeGenerator.NotSupported("Arg_NeverValueType");
}
else {
ilg.Load(null);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
}
ilg.EndIf(); // if (xsiType != null)
ilg.EndIf(); // if (isNull)
}
ilg.Ldloc(typeof(XmlQualifiedName), "xsiType");
ilg.Load(null);
ilg.Ceq();
if (!structMapping.TypeDesc.IsRoot) {
labelTrue = ilg.DefineLabel();
labelEnd = ilg.DefineLabel();
// xsiType == null
ilg.Brtrue(labelTrue);
WriteQNameEqual("xsiType", structMapping.TypeName, structMapping.Namespace);
// Bool result for WriteQNameEqual is on the stack
ilg.Br_S(labelEnd);
ilg.MarkLabel(labelTrue);
ilg.Ldc(true);
ilg.MarkLabel(labelEnd);
}
ilg.If(); // if (xsiType == null
if (structMapping.TypeDesc.IsRoot) {
ConstructorInfo XmlQualifiedName_ctor = typeof(XmlQualifiedName).GetConstructor(
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(String), typeof(String) },
null
);
MethodInfo XmlSerializationReader_ReadTypedPrimitive = typeof(XmlSerializationReader).GetMethod(
"ReadTypedPrimitive",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(XmlQualifiedName) },
null
);
ilg.Ldarg(0);
ilg.Ldstr(Soap.UrType);
ilg.Ldstr(XmlSchema.Namespace);
ilg.New(XmlQualifiedName_ctor);
ilg.Call(XmlSerializationReader_ReadTypedPrimitive);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
}
WriteDerivedTypes(structMapping, !structMapping.TypeDesc.IsRoot, typeName);
if (structMapping.TypeDesc.IsRoot) WriteEnumAndArrayTypes();
ilg.Else(); // if (xsiType == null
if (structMapping.TypeDesc.IsRoot) {
MethodInfo XmlSerializationReader_ReadTypedPrimitive = typeof(XmlSerializationReader).GetMethod(
"ReadTypedPrimitive",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { locXsiType.LocalType },
null
);
ilg.Ldarg(0);
ilg.Ldloc(locXsiType);
ilg.Call(XmlSerializationReader_ReadTypedPrimitive);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
}
else {
MethodInfo XmlSerializationReader_CreateUnknownTypeException = typeof(XmlSerializationReader).GetMethod(
"CreateUnknownTypeException",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(XmlQualifiedName) },
null
);
ilg.Ldarg(0);
ilg.Ldloc(locXsiType);
ilg.Call(XmlSerializationReader_CreateUnknownTypeException);
ilg.Throw();
}
ilg.EndIf(); // if (xsiType == null
ilg.EndIf(); // checkType
if (structMapping.TypeDesc.IsNullable) {
ilg.Ldloc(typeof(bool), "isNull");
ilg.If();
{
ilg.Load(null);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
}
ilg.EndIf();
}
if (structMapping.TypeDesc.IsAbstract) {
MethodInfo XmlSerializationReader_CreateAbstractTypeException = typeof(XmlSerializationReader).GetMethod(
"CreateAbstractTypeException",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(String), typeof(String) },
null
);
ilg.Ldarg(0);
ilg.Ldstr(structMapping.TypeName);
ilg.Ldstr(structMapping.Namespace);
ilg.Call(XmlSerializationReader_CreateAbstractTypeException);
ilg.Throw();
}
else {
if (structMapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(structMapping.TypeDesc.Type)) {
MethodInfo XmlSerializationReader_set_DecodeName = typeof(XmlSerializationReader).GetMethod(
"set_DecodeName",
CodeGenerator.InstanceBindingFlags,
null,
new Type[] { typeof(Boolean) },
null
);
ilg.Ldarg(0);
ilg.Ldc(false);
ilg.Call(XmlSerializationReader_set_DecodeName);
}
WriteCreateMapping(structMapping, "o");
LocalBuilder oLoc = ilg.GetLocal("o");
// this method populates the memberInfos dictionary based on the structMapping
MemberMapping[] mappings = TypeScope.GetSettableMembers(structMapping, memberInfos);
Member anyText = null;
Member anyElement = null;
Member anyAttribute = null;
bool isSequence = structMapping.HasExplicitSequence();
ArrayList arraysToDeclareList = new ArrayList(mappings.Length);
ArrayList arraysToSetList = new ArrayList(mappings.Length);
ArrayList allMembersList = new ArrayList(mappings.Length);
for (int i = 0; i < mappings.Length; i++) {
MemberMapping mapping = mappings[i];
CodeIdentifier.CheckValidIdentifier(mapping.Name);
string source = RaCodeGen.GetStringForMember("o", mapping.Name, structMapping.TypeDesc);
Member member = new Member(this, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
if (!mapping.IsSequence)
member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
member.IsNullable = mapping.TypeDesc.IsNullable;
if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite)
member.CheckSpecifiedSource = RaCodeGen.GetStringForMember("o", mapping.Name + "Specified", structMapping.TypeDesc);
if (mapping.Text != null)
anyText = member;
if (mapping.Attribute != null && mapping.Attribute.Any)
anyAttribute = member;
if (!isSequence) {
// find anyElement if present.
for (int j = 0; j < mapping.Elements.Length; j++) {
if (mapping.Elements[j].Any && (mapping.Elements[j].Name == null || mapping.Elements[j].Name.Length == 0)) {
anyElement = member;
break;
}
}
}
else if (mapping.IsParticle && !mapping.IsSequence) {
StructMapping declaringMapping;
structMapping.FindDeclaringMapping(mapping, out declaringMapping, structMapping.TypeName);
throw new InvalidOperationException(Res.GetString(Res.XmlSequenceHierarchy, structMapping.TypeDesc.FullName, mapping.Name, declaringMapping.TypeDesc.FullName, "Order"));
}
if (mapping.Attribute == null && mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping) {
Member arrayMember = new Member(this, source, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
arrayMember.CheckSpecifiedSource = member.CheckSpecifiedSource;
allMembersList.Add(arrayMember);
}
else {
allMembersList.Add(member);
}
if (mapping.TypeDesc.IsArrayLike) {
arraysToDeclareList.Add(member);
if (mapping.TypeDesc.IsArrayLike && !(mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping)) {
member.ParamsReadSource = null; // flat arrays -- don't want to count params read.
if (member != anyText && member != anyElement) {
arraysToSetList.Add(member);
}
}
else if (!mapping.TypeDesc.IsArray) {
member.ParamsReadSource = null; // collection
}
}
}
if (anyElement != null) arraysToSetList.Add(anyElement);
if (anyText != null && anyText != anyElement) arraysToSetList.Add(anyText);
Member[] arraysToDeclare = (Member[])arraysToDeclareList.ToArray(typeof(Member));
Member[] arraysToSet = (Member[])arraysToSetList.ToArray(typeof(Member));
Member[] allMembers = (Member[])allMembersList.ToArray(typeof(Member));
WriteMemberBegin(arraysToDeclare);
WriteParamsRead(mappings.Length);
WriteAttributes(allMembers, anyAttribute, "UnknownNode", oLoc);
if (anyAttribute != null)
WriteMemberEnd(arraysToDeclare);
MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
"get_Reader",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
MethodInfo XmlReader_MoveToElement = typeof(XmlReader).GetMethod(
"MoveToElement",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_get_Reader);
ilg.Call(XmlReader_MoveToElement);
ilg.Pop();
MethodInfo XmlReader_get_IsEmptyElement = typeof(XmlReader).GetMethod(
"get_IsEmptyElement",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_get_Reader);
ilg.Call(XmlReader_get_IsEmptyElement);
ilg.If();
MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
"Skip",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_get_Reader);
ilg.Call(XmlReader_Skip);
WriteMemberEnd(arraysToSet);
ilg.Ldloc(oLoc);
ilg.Stloc(ilg.ReturnLocal);
ilg.Br(ilg.ReturnLabel);
ilg.EndIf();
MethodInfo XmlReader_ReadStartElement = typeof(XmlReader).GetMethod(
"ReadStartElement",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_get_Reader);
ilg.Call(XmlReader_ReadStartElement);
if (IsSequence(allMembers)) {
ilg.Ldc(0);
ilg.Stloc(typeof(Int32), "state");
}
int loopIndex = WriteWhileNotLoopStart();
string unknownNode = "UnknownNode((object)o, " + ExpectedElements(allMembers) + ");";
WriteMemberElements(allMembers, unknownNode, unknownNode, anyElement, anyText);
MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
"MoveToContent",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_get_Reader);
ilg.Call(XmlReader_MoveToContent);
ilg.Pop();
WriteWhileLoopEnd(loopIndex);
WriteMemberEnd(arraysToSet);
MethodInfo XmlSerializationReader_ReadEndElement = typeof(XmlSerializationReader).GetMethod(
"ReadEndElement",
CodeGenerator.InstanceBindingFlags,
null,
CodeGenerator.EmptyTypeArray,
null
);
ilg.Ldarg(0);
ilg.Call(XmlSerializationReader_ReadEndElement);
ilg.Ldloc(structMapping.TypeDesc.Type, "o");
ilg.Stloc(ilg.ReturnLocal);
}
ilg.MarkLabel(ilg.ReturnLabel);
ilg.Ldloc(ilg.ReturnLocal);
ilg.EndMethod();
}