Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Serialization / XmlSerializationReaderILGen.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSerializationReaderILGen.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>                                                                
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Serialization {
9
10     using System;
11     using System.Collections;
12     using System.Collections.Generic;
13     using System.Diagnostics;
14     using System.Globalization;
15     using System.Reflection;
16     using System.Reflection.Emit;
17     using System.Security;
18     using System.Text.RegularExpressions;
19     using System.Xml;
20     using System.Xml.Schema;
21
22     internal class XmlSerializationReaderILGen : XmlSerializationILGen {
23         Hashtable idNames = new Hashtable();
24         // Mapping name->id_XXXNN field
25         Dictionary<string, FieldBuilder> idNameFields = new Dictionary<string, FieldBuilder>();
26         Hashtable enums;
27         int nextIdNumber = 0;
28         int nextWhileLoopIndex = 0;
29
30         internal Hashtable Enums {
31             get {
32                 if (enums == null) {
33                     enums = new Hashtable();
34                 }
35                 return enums;
36             }
37         }
38
39         class CreateCollectionInfo {
40             string name;
41             TypeDesc td;
42
43             internal CreateCollectionInfo(string name, TypeDesc td) {
44                 this.name = name;
45                 this.td = td;
46             }
47             internal string Name {
48                 get { return name; }
49             }
50
51             internal TypeDesc TypeDesc {
52                 get { return td; }
53             }
54         }
55         class Member {
56             string source;
57             string arrayName;
58             string arraySource;
59             string choiceArrayName;
60             string choiceSource;
61             string choiceArraySource;
62             MemberMapping mapping;
63             bool isArray;
64             bool isList;
65             bool isNullable;
66             bool multiRef;
67             int fixupIndex = -1;
68             string paramsReadSource;
69             string checkSpecifiedSource;
70
71             internal Member(XmlSerializationReaderILGen outerClass, string source, string arrayName, int i, MemberMapping mapping)
72                 : this(outerClass, source, null, arrayName, i, mapping, false, null) {
73             }
74             internal Member(XmlSerializationReaderILGen outerClass, string source, string arrayName, int i, MemberMapping mapping, string choiceSource)
75                 : this(outerClass, source, null, arrayName, i, mapping, false, choiceSource) {
76             }
77             internal Member(XmlSerializationReaderILGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping)
78                 : this(outerClass, source, arraySource, arrayName, i, mapping, false, null) {
79             }
80             internal Member(XmlSerializationReaderILGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping, string choiceSource)
81                 : this(outerClass, source, arraySource, arrayName, i, mapping, false, choiceSource) {
82             }
83             internal Member(XmlSerializationReaderILGen outerClass, string source, string arrayName, int i, MemberMapping mapping, bool multiRef)
84                 : this(outerClass, source, null, arrayName, i, mapping, multiRef, null) {
85             }
86             internal Member(XmlSerializationReaderILGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping, bool multiRef, string choiceSource) {
87                 this.source = source;
88                 this.arrayName = arrayName + "_" + i.ToString(CultureInfo.InvariantCulture);
89                 this.choiceArrayName = "choice_" + this.arrayName;
90                 this.choiceSource = choiceSource;
91
92                 if (mapping.TypeDesc.IsArrayLike) {
93                     if (arraySource != null)
94                         this.arraySource = arraySource;
95                     else
96                         this.arraySource = outerClass.GetArraySource(mapping.TypeDesc, this.arrayName, multiRef);
97                     isArray = mapping.TypeDesc.IsArray;
98                     isList = !isArray;
99                     if (mapping.ChoiceIdentifier != null) {
100                         this.choiceArraySource = outerClass.GetArraySource(mapping.TypeDesc, this.choiceArrayName, multiRef);
101
102                         string a = choiceArrayName;
103                         string c = "c" + a;
104                         string choiceTypeFullName = mapping.ChoiceIdentifier.Mapping.TypeDesc.CSharpName;
105                         string castString = "(" + choiceTypeFullName + "[])";
106
107                         string init = a + " = " + castString +
108                             "EnsureArrayIndex(" + a + ", " + c + ", " + outerClass.RaCodeGen.GetStringForTypeof(choiceTypeFullName) + ");";
109                         this.choiceArraySource = init + outerClass.RaCodeGen.GetStringForArrayMember(a, c + "++", mapping.ChoiceIdentifier.Mapping.TypeDesc);
110                     }
111                     else {
112                         this.choiceArraySource = this.choiceSource;
113                     }
114                 }
115                 else {
116                     this.arraySource = arraySource == null ? source : arraySource;
117                     this.choiceArraySource = this.choiceSource;
118                 }
119                 this.mapping = mapping;
120             }
121
122             internal MemberMapping Mapping {
123                 get { return mapping; }
124             }
125
126             internal string Source {
127                 get { return source; }
128             }
129
130             internal string ArrayName {
131                 get { return arrayName; }
132             }
133
134             internal string ArraySource {
135                 get { return arraySource; }
136             }
137
138             internal bool IsList {
139                 get { return isList; }
140             }
141
142             internal bool IsArrayLike {
143                 get { return (isArray || isList); }
144             }
145
146             internal bool IsNullable {
147                 get { return isNullable; }
148                 set { isNullable = value; }
149             }
150
151             internal bool MultiRef {
152                 get { return multiRef; }
153                 set { multiRef = value; }
154             }
155
156             internal int FixupIndex {
157                 get { return fixupIndex; }
158                 set { fixupIndex = value; }
159             }
160
161             internal string ParamsReadSource {
162                 get { return paramsReadSource; }
163                 set { paramsReadSource = value; }
164             }
165
166             internal string CheckSpecifiedSource {
167                 get { return checkSpecifiedSource; }
168                 set { checkSpecifiedSource = value; }
169             }
170
171             internal string ChoiceSource {
172                 get { return choiceSource; }
173             }
174             internal string ChoiceArrayName {
175                 get { return choiceArrayName; }
176             }
177             internal string ChoiceArraySource {
178                 get { return choiceArraySource; }
179             }
180         }
181
182         internal XmlSerializationReaderILGen(TypeScope[] scopes, string access, string className)
183             : base(scopes, access, className) {
184         }
185
186         internal void GenerateBegin() {
187             this.typeBuilder = CodeGenerator.CreateTypeBuilder(
188                 ModuleBuilder,
189                 ClassName,
190                 TypeAttributes | TypeAttributes.BeforeFieldInit,
191                 typeof(XmlSerializationReader),
192                 CodeGenerator.EmptyTypeArray);
193             foreach (TypeScope scope in Scopes) {
194                 foreach (TypeMapping mapping in scope.TypeMappings) {
195                     if (mapping is StructMapping || mapping is EnumMapping || mapping is NullableMapping)
196                         MethodNames.Add(mapping, NextMethodName(mapping.TypeDesc.Name));
197                 }
198                 RaCodeGen.WriteReflectionInit(scope);
199             }
200         }
201
202         internal override void GenerateMethod(TypeMapping mapping) {
203             if (GeneratedMethods.Contains(mapping))
204                 return;
205
206             GeneratedMethods[mapping] = mapping;
207             if (mapping is StructMapping) {
208                 WriteStructMethod((StructMapping)mapping);
209             }
210             else if (mapping is EnumMapping) {
211                 WriteEnumMethod((EnumMapping)mapping);
212             }
213             else if (mapping is NullableMapping) {
214                 WriteNullableMethod((NullableMapping)mapping);
215             }
216         }
217
218         internal void GenerateEnd(string[] methods, XmlMapping[] xmlMappings, Type[] types) {
219             GenerateReferencedMethods();
220             GenerateInitCallbacksMethod();
221
222             ilg = new CodeGenerator(this.typeBuilder);
223             ilg.BeginMethod(typeof(void), "InitIDs", CodeGenerator.EmptyTypeArray, CodeGenerator.EmptyStringArray,
224                 CodeGenerator.ProtectedOverrideMethodAttributes);
225             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
226                  "get_Reader",
227                  CodeGenerator.InstanceBindingFlags,
228                  null,
229                  CodeGenerator.EmptyTypeArray,
230                  null
231                  );
232             MethodInfo XmlReader_get_NameTable = typeof(XmlReader).GetMethod(
233                 "get_NameTable",
234                 CodeGenerator.InstanceBindingFlags,
235                 null,
236                  CodeGenerator.EmptyTypeArray,
237                 null
238                 );
239             MethodInfo XmlNameTable_Add = typeof(XmlNameTable).GetMethod(
240                 "Add",
241                 CodeGenerator.InstanceBindingFlags,
242                 null,
243                 new Type[] { typeof(String) },
244                 null
245                 );
246             foreach (string id in idNames.Keys) {
247                 // 
248                 ilg.Ldarg(0);
249                 ilg.Ldarg(0);
250                 ilg.Call(XmlSerializationReader_get_Reader);
251                 ilg.Call(XmlReader_get_NameTable);
252                 ilg.Ldstr(id);
253                 ilg.Call(XmlNameTable_Add);
254                 Debug.Assert(idNameFields.ContainsKey(id));
255                 ilg.StoreMember(idNameFields[id]);
256             }
257             ilg.EndMethod();
258
259             this.typeBuilder.DefineDefaultConstructor(
260                 CodeGenerator.PublicMethodAttributes);
261             Type readerType = this.typeBuilder.CreateType();
262             CreatedTypes.Add(readerType.Name, readerType);
263         }
264
265         internal string GenerateElement(XmlMapping xmlMapping) {
266             if (!xmlMapping.IsReadable)
267                 return null;
268             if (!xmlMapping.GenerateSerializer)
269                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
270             if (xmlMapping is XmlTypeMapping)
271                 return GenerateTypeElement((XmlTypeMapping)xmlMapping);
272             else if (xmlMapping is XmlMembersMapping)
273                 return GenerateMembersElement((XmlMembersMapping)xmlMapping);
274             else
275                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
276         }
277
278         void WriteIsStartTag(string name, string ns) {
279             WriteID(name);
280             WriteID(ns);
281             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
282                  "get_Reader",
283                  CodeGenerator.InstanceBindingFlags,
284                  null,
285                  CodeGenerator.EmptyTypeArray,
286                  null
287                  );
288             MethodInfo XmlReader_IsStartElement = typeof(XmlReader).GetMethod(
289                  "IsStartElement",
290                  CodeGenerator.InstanceBindingFlags,
291                  null,
292                  new Type[] { typeof(String), typeof(String) },
293                  null
294                  );
295             ilg.Ldarg(0);
296             ilg.Call(XmlSerializationReader_get_Reader);
297             ilg.Ldarg(0);
298             ilg.LoadMember(idNameFields[name ?? String.Empty]);
299             ilg.Ldarg(0);
300             ilg.LoadMember(idNameFields[ns ?? String.Empty]);
301             ilg.Call(XmlReader_IsStartElement);
302             ilg.If();
303         }
304
305         void WriteUnknownNode(string func, string node, ElementAccessor e, bool anyIfs) {
306             if (anyIfs) {
307                 ilg.Else();
308             }
309             List<Type> argTypes = new List<Type>();
310             ilg.Ldarg(0);
311             Debug.Assert(node == "null" || node == "(object)p");
312             if (node == "null")
313                 ilg.Load(null);
314             else {
315                 object pVar = ilg.GetVariable("p");
316                 ilg.Load(pVar);
317                 ilg.ConvertValue(ilg.GetVariableType(pVar), typeof(object));
318             }
319             argTypes.Add(typeof(object));
320             if (e != null) {
321                 string expectedElement = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
322                 expectedElement += ":";
323                 expectedElement += e.Name;
324                 ilg.Ldstr(ReflectionAwareILGen.GetCSharpString(expectedElement));
325                 argTypes.Add(typeof(string));
326             }
327             MethodInfo method = typeof(XmlSerializationReader).GetMethod(
328                 func,
329                 CodeGenerator.InstanceBindingFlags,
330                 null,
331                 argTypes.ToArray(),
332                 null
333                 );
334             ilg.Call(method);
335             if (anyIfs) {
336                 ilg.EndIf();
337             }
338         }
339
340         void GenerateInitCallbacksMethod() {
341             ilg = new CodeGenerator(this.typeBuilder);
342             ilg.BeginMethod(typeof(void), "InitCallbacks", CodeGenerator.EmptyTypeArray, CodeGenerator.EmptyStringArray,
343                 CodeGenerator.ProtectedOverrideMethodAttributes);
344
345             string dummyArrayMethodName = NextMethodName("Array");
346             bool needDummyArrayMethod = false;
347             ilg.EndMethod();
348
349             if (needDummyArrayMethod) {
350                 ilg.BeginMethod(
351                     typeof(object),
352                     GetMethodBuilder(dummyArrayMethodName),
353                     CodeGenerator.EmptyTypeArray,
354                     CodeGenerator.EmptyStringArray,
355                     CodeGenerator.PrivateMethodAttributes);
356                 MethodInfo XmlSerializationReader_UnknownNode1 = typeof(XmlSerializationReader).GetMethod(
357                       "UnknownNode",
358                       CodeGenerator.InstanceBindingFlags,
359                       null,
360                       new Type[] { typeof(object) },
361                       null
362                       );
363                 ilg.Ldarg(0);
364                 ilg.Load(null);
365                 ilg.Call(XmlSerializationReader_UnknownNode1);
366                 ilg.Load(null);
367                 ilg.EndMethod();
368             }
369         }
370
371
372         string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) {
373             return GenerateLiteralMembersElement(xmlMembersMapping);
374         }
375
376         string GetChoiceIdentifierSource(MemberMapping[] mappings, MemberMapping member) {
377             string choiceSource = null;
378             if (member.ChoiceIdentifier != null) {
379                 for (int j = 0; j < mappings.Length; j++) {
380                     if (mappings[j].Name == member.ChoiceIdentifier.MemberName) {
381                         choiceSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
382                         break;
383                     }
384                 }
385 #if DEBUG
386                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
387                 if (choiceSource == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Can not find " + member.ChoiceIdentifier.MemberName + " in the members mapping."));
388 #endif
389
390             }
391             return choiceSource;
392         }
393
394         string GetChoiceIdentifierSource(MemberMapping mapping, string parent, TypeDesc parentTypeDesc) {
395             if (mapping.ChoiceIdentifier == null) return "";
396             CodeIdentifier.CheckValidIdentifier(mapping.ChoiceIdentifier.MemberName);
397             return RaCodeGen.GetStringForMember(parent, mapping.ChoiceIdentifier.MemberName, parentTypeDesc);
398         }
399
400         string GenerateLiteralMembersElement(XmlMembersMapping xmlMembersMapping) {
401             ElementAccessor element = xmlMembersMapping.Accessor;
402             MemberMapping[] mappings = ((MembersMapping)element.Mapping).Members;
403             bool hasWrapperElement = ((MembersMapping)element.Mapping).HasWrapperElement;
404             string methodName = NextMethodName(element.Name);
405             ilg = new CodeGenerator(this.typeBuilder);
406             ilg.BeginMethod(
407                 typeof(object[]),
408                 methodName,
409                 CodeGenerator.EmptyTypeArray,
410                 CodeGenerator.EmptyStringArray,
411                 CodeGenerator.PublicMethodAttributes
412                 );
413             ilg.Load(null);
414             ilg.Stloc(ilg.ReturnLocal);
415             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
416                 "get_Reader",
417                 CodeGenerator.InstanceBindingFlags,
418                 null,
419                 CodeGenerator.EmptyTypeArray,
420                 null
421                 );
422             MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
423                "MoveToContent",
424                CodeGenerator.InstanceBindingFlags,
425                null,
426                CodeGenerator.EmptyTypeArray,
427                null
428                );
429             ilg.Ldarg(0);
430             ilg.Call(XmlSerializationReader_get_Reader);
431             ilg.Call(XmlReader_MoveToContent);
432             ilg.Pop();
433
434             LocalBuilder localP = ilg.DeclareLocal(typeof(object[]), "p");
435             ilg.NewArray(typeof(object), mappings.Length);
436             ilg.Stloc(localP);
437             InitializeValueTypes("p", mappings);
438
439             int wrapperLoopIndex = 0;
440             if (hasWrapperElement) {
441                 wrapperLoopIndex = WriteWhileNotLoopStart();
442                 WriteIsStartTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
443             }
444
445             Member anyText = null;
446             Member anyElement = null;
447             Member anyAttribute = null;
448
449             ArrayList membersList = new ArrayList();
450             ArrayList textOrArrayMembersList = new ArrayList();
451             ArrayList attributeMembersList = new ArrayList();
452
453             for (int i = 0; i < mappings.Length; i++) {
454                 MemberMapping mapping = mappings[i];
455                 string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
456                 string arraySource = source;
457                 if (mapping.Xmlns != null) {
458                     arraySource = "((" + mapping.TypeDesc.CSharpName + ")" + source + ")";
459                 }
460                 string choiceSource = GetChoiceIdentifierSource(mappings, mapping);
461                 Member member = new Member(this, source, arraySource, "a", i, mapping, choiceSource);
462                 Member anyMember = new Member(this, source, null, "a", i, mapping, choiceSource);
463                 if (!mapping.IsSequence)
464                     member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
465                 if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite) {
466                     string nameSpecified = mapping.Name + "Specified";
467                     for (int j = 0; j < mappings.Length; j++) {
468                         if (mappings[j].Name == nameSpecified) {
469                             member.CheckSpecifiedSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
470                             break;
471                         }
472                     }
473                 }
474                 bool foundAnyElement = false;
475                 if (mapping.Text != null) anyText = anyMember;
476                 if (mapping.Attribute != null && mapping.Attribute.Any)
477                     anyAttribute = anyMember;
478                 if (mapping.Attribute != null || mapping.Xmlns != null)
479                     attributeMembersList.Add(member);
480                 else if (mapping.Text != null)
481                     textOrArrayMembersList.Add(member);
482
483                 if (!mapping.IsSequence) {
484                     for (int j = 0; j < mapping.Elements.Length; j++) {
485                         if (mapping.Elements[j].Any && mapping.Elements[j].Name.Length == 0) {
486                             anyElement = anyMember;
487                             if (mapping.Attribute == null && mapping.Text == null)
488                                 textOrArrayMembersList.Add(anyMember);
489                             foundAnyElement = true;
490                             break;
491                         }
492                     }
493                 }
494                 if (mapping.Attribute != null || mapping.Text != null || foundAnyElement)
495                     membersList.Add(anyMember);
496                 else if (mapping.TypeDesc.IsArrayLike && !(mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping)) {
497                     membersList.Add(anyMember);
498                     textOrArrayMembersList.Add(anyMember);
499                 }
500                 else {
501                     if (mapping.TypeDesc.IsArrayLike && !mapping.TypeDesc.IsArray)
502                         member.ParamsReadSource = null; // collection
503                     membersList.Add(member);
504                 }
505             }
506             Member[] members = (Member[])membersList.ToArray(typeof(Member));
507             Member[] textOrArrayMembers = (Member[])textOrArrayMembersList.ToArray(typeof(Member));
508
509             if (members.Length > 0 && members[0].Mapping.IsReturnValue) {
510                 MethodInfo XmlSerializationReader_set_IsReturnValue = typeof(XmlSerializationReader).GetMethod(
511                     "set_IsReturnValue",
512                     CodeGenerator.InstanceBindingFlags,
513                     null,
514                     new Type[] { typeof(Boolean) },
515                     null
516                     );
517                 ilg.Ldarg(0);
518                 ilg.Ldc(true);
519                 ilg.Call(XmlSerializationReader_set_IsReturnValue);
520             }
521
522             WriteParamsRead(mappings.Length);
523
524             if (attributeMembersList.Count > 0) {
525                 Member[] attributeMembers = (Member[])attributeMembersList.ToArray(typeof(Member));
526                 WriteMemberBegin(attributeMembers);
527                 WriteAttributes(attributeMembers, anyAttribute, "UnknownNode", localP);
528                 WriteMemberEnd(attributeMembers);
529                 MethodInfo XmlReader_MoveToElement = typeof(XmlReader).GetMethod(
530                     "MoveToElement",
531                     CodeGenerator.InstanceBindingFlags,
532                     null,
533                     CodeGenerator.EmptyTypeArray,
534                     null
535                     );
536                 ilg.Ldarg(0);
537                 ilg.Call(XmlSerializationReader_get_Reader);
538                 ilg.Call(XmlReader_MoveToElement);
539                 ilg.Pop();
540             }
541
542             WriteMemberBegin(textOrArrayMembers);
543
544             if (hasWrapperElement) {
545                 MethodInfo XmlReader_get_IsEmptyElement = typeof(XmlReader).GetMethod(
546                     "get_IsEmptyElement",
547                     CodeGenerator.InstanceBindingFlags,
548                     null,
549                     CodeGenerator.EmptyTypeArray,
550                     null
551                     );
552                 ilg.Ldarg(0);
553                 ilg.Call(XmlSerializationReader_get_Reader);
554                 ilg.Call(XmlReader_get_IsEmptyElement);
555                 ilg.If();
556                 {
557                     MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
558                         "Skip",
559                         CodeGenerator.InstanceBindingFlags,
560                         null,
561                         CodeGenerator.EmptyTypeArray,
562                         null
563                         );
564                     ilg.Ldarg(0);
565                     ilg.Call(XmlSerializationReader_get_Reader);
566                     ilg.Call(XmlReader_Skip);
567                     ilg.Ldarg(0);
568                     ilg.Call(XmlSerializationReader_get_Reader);
569                     ilg.Call(XmlReader_MoveToContent);
570                     ilg.Pop();
571                     ilg.WhileContinue();
572                 }
573                 ilg.EndIf();
574                 MethodInfo XmlReader_ReadStartElement = typeof(XmlReader).GetMethod(
575                     "ReadStartElement",
576                     CodeGenerator.InstanceBindingFlags,
577                     null,
578                     CodeGenerator.EmptyTypeArray,
579                     null
580                     );
581                 ilg.Ldarg(0);
582                 ilg.Call(XmlSerializationReader_get_Reader);
583                 ilg.Call(XmlReader_ReadStartElement);
584             }
585             if (IsSequence(members)) {
586                 ilg.Ldc(0);
587                 ilg.Stloc(typeof(Int32), "state");
588             }
589             int loopIndex = WriteWhileNotLoopStart();
590
591             string unknownNode = "UnknownNode((object)p, " + ExpectedElements(members) + ");";
592             WriteMemberElements(members, unknownNode, unknownNode, anyElement, anyText);
593
594             ilg.Ldarg(0);
595             ilg.Call(XmlSerializationReader_get_Reader);
596             ilg.Call(XmlReader_MoveToContent);
597             ilg.Pop();
598             WriteWhileLoopEnd(loopIndex);
599
600             WriteMemberEnd(textOrArrayMembers);
601
602             if (hasWrapperElement) {
603                 MethodInfo XmlSerializationReader_ReadEndElement = typeof(XmlSerializationReader).GetMethod(
604                     "ReadEndElement",
605                     CodeGenerator.InstanceBindingFlags,
606                     null,
607                     CodeGenerator.EmptyTypeArray,
608                     null
609                     );
610                 ilg.Ldarg(0);
611                 ilg.Call(XmlSerializationReader_ReadEndElement);
612
613
614                 WriteUnknownNode("UnknownNode", "null", element, true);
615
616                 ilg.Ldarg(0);
617                 ilg.Call(XmlSerializationReader_get_Reader);
618                 ilg.Call(XmlReader_MoveToContent);
619                 ilg.Pop();
620                 WriteWhileLoopEnd(wrapperLoopIndex);
621             }
622
623             ilg.Ldloc(ilg.GetLocal("p"));
624             ilg.EndMethod();
625
626             return methodName;
627         }
628
629         void InitializeValueTypes(string arrayName, MemberMapping[] mappings) {
630             for (int i = 0; i < mappings.Length; i++) {
631                 if (!mappings[i].TypeDesc.IsValueType)
632                     continue;
633                 LocalBuilder arrayLoc = ilg.GetLocal(arrayName);
634                 ilg.Ldloc(arrayLoc);
635                 ilg.Ldc(i);
636                 RaCodeGen.ILGenForCreateInstance(ilg, mappings[i].TypeDesc.Type, false, false);
637                 ilg.ConvertValue(mappings[i].TypeDesc.Type, typeof(object));
638                 ilg.Stelem(arrayLoc.LocalType.GetElementType());
639             }
640         }
641
642         string GenerateTypeElement(XmlTypeMapping xmlTypeMapping) {
643             ElementAccessor element = xmlTypeMapping.Accessor;
644             TypeMapping mapping = element.Mapping;
645             string methodName = NextMethodName(element.Name);
646             ilg = new CodeGenerator(this.typeBuilder);
647             ilg.BeginMethod(
648                 typeof(object),
649                 methodName,
650                 CodeGenerator.EmptyTypeArray,
651                 CodeGenerator.EmptyStringArray,
652                 CodeGenerator.PublicMethodAttributes
653                 );
654             LocalBuilder oLoc = ilg.DeclareLocal(typeof(object), "o");
655             ilg.Load(null);
656             ilg.Stloc(oLoc);
657             MemberMapping member = new MemberMapping();
658             member.TypeDesc = mapping.TypeDesc;
659             //member.ReadOnly = !mapping.TypeDesc.HasDefaultConstructor;
660             member.Elements = new ElementAccessor[] { element };
661             Member[] members = new Member[] { new Member(this, "o", "o", "a", 0, member) };
662             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
663                 "get_Reader",
664                 CodeGenerator.InstanceBindingFlags,
665                 null,
666                 CodeGenerator.EmptyTypeArray,
667                 null
668                 );
669             MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
670                "MoveToContent",
671                CodeGenerator.InstanceBindingFlags,
672                null,
673                CodeGenerator.EmptyTypeArray,
674                null
675                );
676             ilg.Ldarg(0);
677             ilg.Call(XmlSerializationReader_get_Reader);
678             ilg.Call(XmlReader_MoveToContent);
679             ilg.Pop();
680             string unknownNode = "UnknownNode(null, " + ExpectedElements(members) + ");";
681             WriteMemberElements(members, "throw CreateUnknownNodeException();", unknownNode, element.Any ? members[0] : null, null);
682             ilg.Ldloc(oLoc);
683             // for code compat as compiler does
684             ilg.Stloc(ilg.ReturnLocal);
685             ilg.Ldloc(ilg.ReturnLocal);
686             ilg.EndMethod();
687             return methodName;
688         }
689
690         string NextMethodName(string name) {
691             return "Read" + (++NextMethodNumber).ToString(CultureInfo.InvariantCulture) + "_" + CodeIdentifier.MakeValidInternal(name);
692         }
693
694         string NextIdName(string name) {
695             return "id" + (++nextIdNumber).ToString(CultureInfo.InvariantCulture) + "_" + CodeIdentifier.MakeValidInternal(name);
696         }
697
698         void WritePrimitive(TypeMapping mapping, string source) {
699             System.Diagnostics.Debug.Assert(source == "Reader.ReadElementString()" || source == "Reader.ReadString()"
700                 || source == "false" || source == "Reader.Value" || source == "vals[i]");
701             if (mapping is EnumMapping) {
702                 string enumMethodName = ReferenceMapping(mapping);
703                 if (enumMethodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlMissingMethodEnum, mapping.TypeDesc.Name));
704                 // For enum, its read method (eg. Read1_Gender) could be called multiple times
705                 // prior to its declaration.
706                 MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
707                     enumMethodName,
708                     CodeGenerator.PrivateMethodAttributes,
709                     mapping.TypeDesc.Type,
710                     new Type[] { typeof(string) }
711                     );
712                 ilg.Ldarg(0);
713                 if (source == "Reader.ReadElementString()" || source == "Reader.ReadString()") {
714                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
715                          "get_Reader",
716                          CodeGenerator.InstanceBindingFlags,
717                          null,
718                          CodeGenerator.EmptyTypeArray,
719                          null
720                          );
721                     MethodInfo XmlReader_ReadXXXString = typeof(XmlReader).GetMethod(
722                         source == "Reader.ReadElementString()" ? "ReadElementString" : "ReadString",
723                         CodeGenerator.InstanceBindingFlags,
724                         null,
725                         CodeGenerator.EmptyTypeArray,
726                         null
727                         );
728                     ilg.Ldarg(0);
729                     ilg.Call(XmlSerializationReader_get_Reader);
730                     ilg.Call(XmlReader_ReadXXXString);
731                 }
732                 else if (source == "Reader.Value") {
733                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
734                          "get_Reader",
735                          CodeGenerator.InstanceBindingFlags,
736                          null,
737                          CodeGenerator.EmptyTypeArray,
738                          null
739                          );
740                     MethodInfo XmlReader_get_Value = typeof(XmlReader).GetMethod(
741                           "get_Value",
742                           CodeGenerator.InstanceBindingFlags,
743                           null,
744                           CodeGenerator.EmptyTypeArray,
745                           null
746                           );
747                     ilg.Ldarg(0);
748                     ilg.Call(XmlSerializationReader_get_Reader);
749                     ilg.Call(XmlReader_get_Value);
750                 }
751                 else if (source == "vals[i]") {
752                     LocalBuilder locVals = ilg.GetLocal("vals");
753                     LocalBuilder locI = ilg.GetLocal("i");
754                     ilg.LoadArrayElement(locVals, locI);
755                 }
756                 else if (source == "false") {
757                     ilg.Ldc(false);
758                 }
759                 else {
760                     throw CodeGenerator.NotSupported("Unexpected: " + source);
761                 }
762                 ilg.Call(methodBuilder);
763             }
764             else if (mapping.TypeDesc == StringTypeDesc) {
765                 if (source == "Reader.ReadElementString()" || source == "Reader.ReadString()") {
766                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
767                          "get_Reader",
768                          CodeGenerator.InstanceBindingFlags,
769                          null,
770                          CodeGenerator.EmptyTypeArray,
771                          null
772                          );
773                     MethodInfo XmlReader_ReadXXXString = typeof(XmlReader).GetMethod(
774                         source == "Reader.ReadElementString()" ? "ReadElementString" : "ReadString",
775                         CodeGenerator.InstanceBindingFlags,
776                         null,
777                         CodeGenerator.EmptyTypeArray,
778                         null
779                         );
780                     ilg.Ldarg(0);
781                     ilg.Call(XmlSerializationReader_get_Reader);
782                     ilg.Call(XmlReader_ReadXXXString);
783                 }
784                 else if (source == "Reader.Value") {
785                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
786                          "get_Reader",
787                          CodeGenerator.InstanceBindingFlags,
788                          null,
789                          CodeGenerator.EmptyTypeArray,
790                          null
791                          );
792                     MethodInfo XmlReader_get_Value = typeof(XmlReader).GetMethod(
793                           "get_Value",
794                           CodeGenerator.InstanceBindingFlags,
795                           null,
796                           CodeGenerator.EmptyTypeArray,
797                           null
798                           );
799                     ilg.Ldarg(0);
800                     ilg.Call(XmlSerializationReader_get_Reader);
801                     ilg.Call(XmlReader_get_Value);
802                 }
803                 else if (source == "vals[i]") {
804                     LocalBuilder locVals = ilg.GetLocal("vals");
805                     LocalBuilder locI = ilg.GetLocal("i");
806                     ilg.LoadArrayElement(locVals, locI);
807                 }
808                 else {
809                     throw CodeGenerator.NotSupported("Unexpected: " + source);
810                 }
811             }
812             else if (mapping.TypeDesc.FormatterName == "String") {
813                 if (source == "vals[i]") {
814                     if (mapping.TypeDesc.CollapseWhitespace)
815                         ilg.Ldarg(0);
816                     LocalBuilder locVals = ilg.GetLocal("vals");
817                     LocalBuilder locI = ilg.GetLocal("i");
818                     ilg.LoadArrayElement(locVals, locI);
819                     if (mapping.TypeDesc.CollapseWhitespace) {
820                         MethodInfo XmlSerializationReader_CollapseWhitespace = typeof(XmlSerializationReader).GetMethod(
821                             "CollapseWhitespace",
822                             CodeGenerator.InstanceBindingFlags,
823                             null,
824                             new Type[] { typeof(String) },
825                             null
826                             );
827                         ilg.Call(XmlSerializationReader_CollapseWhitespace);
828                     }
829                 }
830                 else {
831                     System.Diagnostics.Debug.Assert(source == "Reader.Value" || source == "Reader.ReadElementString()");
832                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
833                          "get_Reader",
834                          CodeGenerator.InstanceBindingFlags,
835                          null,
836                          CodeGenerator.EmptyTypeArray,
837                          null
838                          );
839                     MethodInfo XmlReader_method = typeof(XmlReader).GetMethod(
840                         source == "Reader.Value" ? "get_Value" : "ReadElementString",
841                         CodeGenerator.InstanceBindingFlags,
842                         null,
843                         CodeGenerator.EmptyTypeArray,
844                         null
845                         );
846                     if (mapping.TypeDesc.CollapseWhitespace)
847                         ilg.Ldarg(0);
848                     ilg.Ldarg(0);
849                     ilg.Call(XmlSerializationReader_get_Reader);
850                     ilg.Call(XmlReader_method);
851                     if (mapping.TypeDesc.CollapseWhitespace) {
852                         MethodInfo XmlSerializationReader_CollapseWhitespace = typeof(XmlSerializationReader).GetMethod(
853                             "CollapseWhitespace",
854                             CodeGenerator.InstanceBindingFlags,
855                             null,
856                             new Type[] { typeof(String) },
857                             null
858                             );
859                         ilg.Call(XmlSerializationReader_CollapseWhitespace);
860                     }
861                 }
862             }
863             else {
864                 Type argType = source == "false" ? typeof(Boolean) : typeof(String);
865                 MethodInfo ToXXX;
866                 if (mapping.TypeDesc.HasCustomFormatter) {
867
868                     // Only these methods below that is non Static and need to ldarg("this") for Call.
869                     BindingFlags bindingFlags = CodeGenerator.StaticBindingFlags;
870                     if ((mapping.TypeDesc.FormatterName == "ByteArrayBase64" && source == "false")
871                         || (mapping.TypeDesc.FormatterName == "ByteArrayHex" && source == "false")
872                         || (mapping.TypeDesc.FormatterName == "XmlQualifiedName")) {
873                         bindingFlags = CodeGenerator.InstanceBindingFlags;
874                         ilg.Ldarg(0);
875                     }
876
877                     ToXXX = typeof(XmlSerializationReader).GetMethod(
878                         "To" + mapping.TypeDesc.FormatterName,
879                         bindingFlags,
880                         null,
881                         new Type[] { argType },
882                         null
883                         );
884                 }
885                 else {
886                     ToXXX = typeof(XmlConvert).GetMethod(
887                         "To" + mapping.TypeDesc.FormatterName,
888                         CodeGenerator.StaticBindingFlags,
889                         null,
890                         new Type[] { argType },
891                         null
892                         );
893                 }
894                 if (source == "Reader.ReadElementString()" || source == "Reader.ReadString()") {
895                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
896                          "get_Reader",
897                          CodeGenerator.InstanceBindingFlags,
898                          null,
899                          CodeGenerator.EmptyTypeArray,
900                          null
901                          );
902                     MethodInfo XmlReader_ReadXXXString = typeof(XmlReader).GetMethod(
903                         source == "Reader.ReadElementString()" ? "ReadElementString" : "ReadString",
904                         CodeGenerator.InstanceBindingFlags,
905                         null,
906                         CodeGenerator.EmptyTypeArray,
907                         null
908                         );
909                     ilg.Ldarg(0);
910                     ilg.Call(XmlSerializationReader_get_Reader);
911                     ilg.Call(XmlReader_ReadXXXString);
912                 }
913                 else if (source == "Reader.Value") {
914                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
915                          "get_Reader",
916                          CodeGenerator.InstanceBindingFlags,
917                          null,
918                          CodeGenerator.EmptyTypeArray,
919                          null
920                          );
921                     MethodInfo XmlReader_get_Value = typeof(XmlReader).GetMethod(
922                           "get_Value",
923                           CodeGenerator.InstanceBindingFlags,
924                           null,
925                           CodeGenerator.EmptyTypeArray,
926                           null
927                           );
928                     ilg.Ldarg(0);
929                     ilg.Call(XmlSerializationReader_get_Reader);
930                     ilg.Call(XmlReader_get_Value);
931                 }
932                 else if (source == "vals[i]") {
933                     LocalBuilder locVals = ilg.GetLocal("vals");
934                     LocalBuilder locI = ilg.GetLocal("i");
935                     ilg.LoadArrayElement(locVals, locI);
936                 }
937                 else {
938                     System.Diagnostics.Debug.Assert(source == "false");
939                     ilg.Ldc(false);
940                 }
941                 ilg.Call(ToXXX);
942             }
943         }
944
945         string MakeUnique(EnumMapping mapping, string name) {
946             string uniqueName = name;
947             object m = Enums[uniqueName];
948             if (m != null) {
949                 if (m == mapping) {
950                     // we already have created the hashtable
951                     return null;
952                 }
953                 int i = 0;
954                 while (m != null) {
955                     i++;
956                     uniqueName = name + i.ToString(CultureInfo.InvariantCulture);
957                     m = Enums[uniqueName];
958                 }
959             }
960             Enums.Add(uniqueName, mapping);
961             return uniqueName;
962         }
963
964         string WriteHashtable(EnumMapping mapping, string typeName, out MethodBuilder get_TableName) {
965             get_TableName = null;
966
967             CodeIdentifier.CheckValidIdentifier(typeName);
968             string propName = MakeUnique(mapping, typeName + "Values");
969             if (propName == null) return CodeIdentifier.GetCSharpName(typeName);
970             string memberName = MakeUnique(mapping, "_" + propName);
971             propName = CodeIdentifier.GetCSharpName(propName);
972
973             FieldBuilder fieldBuilder = this.typeBuilder.DefineField(
974                 memberName,
975                 typeof(Hashtable),
976                 FieldAttributes.Private
977                 );
978
979             PropertyBuilder propertyBuilder = this.typeBuilder.DefineProperty(
980                 propName,
981                 PropertyAttributes.None,
982                 CallingConventions.HasThis,
983                 typeof(Hashtable),
984                 null, null, null, null, null);
985
986             ilg = new CodeGenerator(this.typeBuilder);
987             ilg.BeginMethod(
988                 typeof(Hashtable),
989                 "get_" + propName,
990                 CodeGenerator.EmptyTypeArray,
991                 CodeGenerator.EmptyStringArray,
992                 MethodAttributes.Assembly | MethodAttributes.HideBySig | MethodAttributes.SpecialName);
993
994             ilg.Ldarg(0);
995             ilg.LoadMember(fieldBuilder);
996             ilg.Load(null);
997             ilg.If(Cmp.EqualTo);
998
999             ConstructorInfo Hashtable_ctor = typeof(Hashtable).GetConstructor(
1000                 CodeGenerator.InstanceBindingFlags,
1001                 null,
1002                 CodeGenerator.EmptyTypeArray,
1003                 null
1004                 );
1005             LocalBuilder hLoc = ilg.DeclareLocal(typeof(Hashtable), "h");
1006             ilg.New(Hashtable_ctor);
1007             ilg.Stloc(hLoc);
1008
1009             ConstantMapping[] constants = mapping.Constants;
1010             MethodInfo Hashtable_Add = typeof(Hashtable).GetMethod(
1011                 "Add",
1012                 CodeGenerator.InstanceBindingFlags,
1013                 null,
1014                 new Type[] { typeof(Object), typeof(Object) },
1015                 null
1016                 );
1017
1018             for (int i = 0; i < constants.Length; i++) {
1019                 ilg.Ldloc(hLoc);
1020                 ilg.Ldstr(constants[i].XmlName);
1021                 ilg.Ldc(Enum.ToObject(mapping.TypeDesc.Type, constants[i].Value));
1022                 ilg.ConvertValue(mapping.TypeDesc.Type, typeof(long));
1023                 ilg.ConvertValue(typeof(long), typeof(Object));
1024
1025                 ilg.Call(Hashtable_Add);
1026             }
1027
1028             ilg.Ldarg(0);
1029             ilg.Ldloc(hLoc);
1030             ilg.StoreMember(fieldBuilder);
1031
1032             ilg.EndIf();
1033
1034             ilg.Ldarg(0);
1035             ilg.LoadMember(fieldBuilder);
1036
1037             get_TableName = ilg.EndMethod();
1038             propertyBuilder.SetGetMethod(get_TableName);
1039
1040             return propName;
1041         }
1042
1043         void WriteEnumMethod(EnumMapping mapping) {
1044             MethodBuilder get_TableName = null;
1045             if (mapping.IsFlags)
1046                 WriteHashtable(mapping, mapping.TypeDesc.Name, out get_TableName);
1047
1048             string methodName = (string)MethodNames[mapping];
1049             string fullTypeName = mapping.TypeDesc.CSharpName;
1050             List<Type> argTypes = new List<Type>();
1051             List<string> argNames = new List<string>();
1052             Type returnType;
1053             Type underlyingType;
1054
1055             returnType = mapping.TypeDesc.Type;
1056             underlyingType = Enum.GetUnderlyingType(returnType);
1057             argTypes.Add(typeof(string));
1058             argNames.Add("s");
1059             ilg = new CodeGenerator(this.typeBuilder);
1060             ilg.BeginMethod(
1061                 returnType,
1062                 GetMethodBuilder(methodName),
1063                 argTypes.ToArray(),
1064                 argNames.ToArray(),
1065                 CodeGenerator.PrivateMethodAttributes);
1066
1067             ConstantMapping[] constants = mapping.Constants;
1068             if (mapping.IsFlags) {
1069                 {
1070                     MethodInfo XmlSerializationReader_ToEnum = typeof(XmlSerializationReader).GetMethod(
1071                         "ToEnum",
1072                         CodeGenerator.StaticBindingFlags,
1073                         null,
1074                         new Type[] { typeof(String), typeof(Hashtable), typeof(String) },
1075                         null
1076                         );
1077                     ilg.Ldarg("s");
1078                     ilg.Ldarg(0);
1079                     Debug.Assert(get_TableName != null);
1080                     ilg.Call(get_TableName);
1081                     ilg.Ldstr(fullTypeName);
1082                     ilg.Call(XmlSerializationReader_ToEnum);
1083                     // XmlSerializationReader_ToEnum return long!
1084                     if (underlyingType != typeof(long)) {
1085                         ilg.ConvertValue(typeof(long), underlyingType);
1086                     }
1087                     ilg.Stloc(ilg.ReturnLocal);
1088                     ilg.Br(ilg.ReturnLabel);
1089                 }
1090             }
1091             else {
1092                 List<Label> caseLabels = new List<Label>();
1093                 List<object> retValues = new List<object>();
1094                 Label defaultLabel = ilg.DefineLabel();
1095                 Label endSwitchLabel = ilg.DefineLabel();
1096                 // This local is necessary; otherwise, it becomes if/else
1097                 LocalBuilder localTmp = ilg.GetTempLocal(typeof(string));
1098                 ilg.Ldarg("s");
1099                 ilg.Stloc(localTmp);
1100                 ilg.Ldloc(localTmp);
1101                 ilg.Brfalse(defaultLabel);
1102                 Hashtable cases = new Hashtable();
1103                 for (int i = 0; i < constants.Length; i++) {
1104                     ConstantMapping c = constants[i];
1105
1106                     CodeIdentifier.CheckValidIdentifier(c.Name);
1107                     if (cases[c.XmlName] == null) {
1108                         cases[c.XmlName] = c.XmlName;
1109                         Label caseLabel = ilg.DefineLabel();
1110                         ilg.Ldloc(localTmp);
1111                         ilg.Ldstr(c.XmlName);
1112                         MethodInfo String_op_Equality = typeof(string).GetMethod(
1113                             "op_Equality",
1114                             CodeGenerator.StaticBindingFlags,
1115                             null,
1116                             new Type[] { typeof(string), typeof(string) },
1117                             null
1118                             );
1119                         ilg.Call(String_op_Equality);
1120                         ilg.Brtrue(caseLabel);
1121                         caseLabels.Add(caseLabel);
1122                         retValues.Add(Enum.ToObject(mapping.TypeDesc.Type, c.Value));
1123                     }
1124                 }
1125
1126                 ilg.Br(defaultLabel);
1127                 // Case bodies
1128                 for (int i = 0; i < caseLabels.Count; i++) {
1129                     ilg.MarkLabel(caseLabels[i]);
1130                     ilg.Ldc(retValues[i]);
1131                     ilg.Stloc(ilg.ReturnLocal);
1132                     ilg.Br(ilg.ReturnLabel);
1133                 }
1134                 MethodInfo XmlSerializationReader_CreateUnknownConstantException = typeof(XmlSerializationReader).GetMethod(
1135                     "CreateUnknownConstantException",
1136                     CodeGenerator.InstanceBindingFlags,
1137                     null,
1138                     new Type[] { typeof(string), typeof(Type) },
1139                     null
1140                     );
1141                 // Default body
1142                 ilg.MarkLabel(defaultLabel);
1143                 ilg.Ldarg(0);
1144                 ilg.Ldarg("s");
1145                 // typeof(..)
1146                 ilg.Ldc(mapping.TypeDesc.Type);
1147                 ilg.Call(XmlSerializationReader_CreateUnknownConstantException);
1148                 ilg.Throw();
1149                 // End switch
1150                 ilg.MarkLabel(endSwitchLabel);
1151             }
1152
1153             ilg.MarkLabel(ilg.ReturnLabel);
1154             ilg.Ldloc(ilg.ReturnLocal);
1155             ilg.EndMethod();
1156         }
1157
1158         void WriteDerivedTypes(StructMapping mapping, bool isTypedReturn, string returnTypeName) {
1159
1160             for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
1161                 ilg.InitElseIf();
1162                 WriteQNameEqual("xsiType", derived.TypeName, derived.Namespace);
1163                 ilg.AndIf();
1164
1165                 string methodName = ReferenceMapping(derived);
1166 #if DEBUG
1167                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
1168                 if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, derived.TypeDesc.Name));
1169 #endif
1170
1171                 List<Type> argTypes = new List<Type>();
1172                 ilg.Ldarg(0);
1173                 if (derived.TypeDesc.IsNullable) {
1174                     ilg.Ldarg("isNullable");
1175                     argTypes.Add(typeof(Boolean));
1176                 }
1177                 ilg.Ldc(false);
1178                 argTypes.Add(typeof(Boolean));
1179
1180                 MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
1181                     methodName,
1182                     CodeGenerator.PrivateMethodAttributes,
1183                     derived.TypeDesc.Type,
1184                     argTypes.ToArray()
1185                     );
1186                 ilg.Call(methodBuilder);
1187                 ilg.ConvertValue(methodBuilder.ReturnType, ilg.ReturnLocal.LocalType);
1188                 ilg.Stloc(ilg.ReturnLocal);
1189                 ilg.Br(ilg.ReturnLabel);
1190
1191                 WriteDerivedTypes(derived, isTypedReturn, returnTypeName);
1192             }
1193         }
1194
1195         void WriteEnumAndArrayTypes() {
1196             foreach (TypeScope scope in Scopes) {
1197                 foreach (Mapping m in scope.TypeMappings) {
1198                     if (m is EnumMapping) {
1199                         EnumMapping mapping = (EnumMapping)m;
1200                         ilg.InitElseIf();
1201                         WriteQNameEqual("xsiType", mapping.TypeName, mapping.Namespace);
1202                         ilg.AndIf();
1203                         MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
1204                             "get_Reader",
1205                             CodeGenerator.InstanceBindingFlags,
1206                             null,
1207                             CodeGenerator.EmptyTypeArray,
1208                             null
1209                             );
1210                         MethodInfo XmlReader_ReadStartElement = typeof(XmlReader).GetMethod(
1211                             "ReadStartElement",
1212                             CodeGenerator.InstanceBindingFlags,
1213                             null,
1214                             CodeGenerator.EmptyTypeArray,
1215                             null
1216                             );
1217                         ilg.Ldarg(0);
1218                         ilg.Call(XmlSerializationReader_get_Reader);
1219                         ilg.Call(XmlReader_ReadStartElement);
1220                         string methodName = ReferenceMapping(mapping);
1221 #if DEBUG
1222                         // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
1223                         if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name));
1224 #endif
1225                         LocalBuilder eLoc = ilg.DeclareOrGetLocal(typeof(object), "e");
1226                         MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
1227                             methodName,
1228                             CodeGenerator.PrivateMethodAttributes,
1229                             mapping.TypeDesc.Type,
1230                             new Type[] { typeof(string) }
1231                             );
1232                         MethodInfo XmlSerializationReader_CollapseWhitespace = typeof(XmlSerializationReader).GetMethod(
1233                             "CollapseWhitespace",
1234                             CodeGenerator.InstanceBindingFlags,
1235                             null,
1236                             new Type[] { typeof(String) },
1237                             null
1238                             );
1239                         MethodInfo XmlReader_ReadString = typeof(XmlReader).GetMethod(
1240                             "ReadString",
1241                             CodeGenerator.InstanceBindingFlags,
1242                             null,
1243                             CodeGenerator.EmptyTypeArray,
1244                             null
1245                             );
1246                         ilg.Ldarg(0);
1247                         ilg.Ldarg(0);
1248                         ilg.Ldarg(0);
1249                         ilg.Call(XmlSerializationReader_get_Reader);
1250                         ilg.Call(XmlReader_ReadString);
1251                         ilg.Call(XmlSerializationReader_CollapseWhitespace);
1252                         ilg.Call(methodBuilder);
1253                         ilg.ConvertValue(methodBuilder.ReturnType, eLoc.LocalType);
1254                         ilg.Stloc(eLoc);
1255                         MethodInfo XmlSerializationReader_ReadEndElement = typeof(XmlSerializationReader).GetMethod(
1256                             "ReadEndElement",
1257                             CodeGenerator.InstanceBindingFlags,
1258                             null,
1259                             CodeGenerator.EmptyTypeArray,
1260                             null
1261                             );
1262                         ilg.Ldarg(0);
1263                         ilg.Call(XmlSerializationReader_ReadEndElement);
1264                         ilg.Ldloc(eLoc);
1265                         ilg.Stloc(ilg.ReturnLocal);
1266                         ilg.Br(ilg.ReturnLabel);
1267                         // Caller own calling ilg.EndIf();
1268                     }
1269                     else if (m is ArrayMapping) {
1270                         ArrayMapping mapping = (ArrayMapping)m;
1271                         if (mapping.TypeDesc.HasDefaultConstructor) {
1272                             ilg.InitElseIf();
1273                             WriteQNameEqual("xsiType", mapping.TypeName, mapping.Namespace);
1274                             ilg.AndIf();
1275                             ilg.EnterScope();
1276                             MemberMapping memberMapping = new MemberMapping();
1277                             memberMapping.TypeDesc = mapping.TypeDesc;
1278                             memberMapping.Elements = mapping.Elements;
1279                             string aVar = "a";
1280                             string zVar = "z";
1281                             Member member = new Member(this, aVar, zVar, 0, memberMapping);
1282
1283                             TypeDesc td = mapping.TypeDesc;
1284                             LocalBuilder aLoc = ilg.DeclareLocal(mapping.TypeDesc.Type, aVar);
1285                             if (mapping.TypeDesc.IsValueType) {
1286                                 RaCodeGen.ILGenForCreateInstance(ilg, td.Type, false, false);
1287                             }
1288                             else
1289                                 ilg.Load(null);
1290                             ilg.Stloc(aLoc);
1291
1292                             WriteArray(member.Source, member.ArrayName, mapping, false, false, -1, 0);
1293                             ilg.Ldloc(aLoc);
1294                             ilg.Stloc(ilg.ReturnLocal);
1295                             ilg.Br(ilg.ReturnLabel);
1296                             ilg.ExitScope();
1297                             // Caller own calling ilg.EndIf();
1298                         }
1299                     }
1300                 }
1301             }
1302         }
1303
1304         void WriteNullableMethod(NullableMapping nullableMapping) {
1305             string methodName = (string)MethodNames[nullableMapping];
1306             ilg = new CodeGenerator(this.typeBuilder);
1307             ilg.BeginMethod(
1308                 nullableMapping.TypeDesc.Type,
1309                 GetMethodBuilder(methodName),
1310                 new Type[] { typeof(Boolean) },
1311                 new string[] { "checkType" },
1312                 CodeGenerator.PrivateMethodAttributes);
1313
1314             LocalBuilder oLoc = ilg.DeclareLocal(nullableMapping.TypeDesc.Type, "o");
1315
1316             ilg.LoadAddress(oLoc);
1317             ilg.InitObj(nullableMapping.TypeDesc.Type);
1318             MethodInfo XmlSerializationReader_ReadNull = typeof(XmlSerializationReader).GetMethod(
1319                 "ReadNull",
1320                 CodeGenerator.InstanceBindingFlags,
1321                 null,
1322                 CodeGenerator.EmptyTypeArray,
1323                 null);
1324             ilg.Ldarg(0);
1325             ilg.Call(XmlSerializationReader_ReadNull);
1326             ilg.If();
1327             {
1328                 ilg.Ldloc(oLoc);
1329                 ilg.Stloc(ilg.ReturnLocal);
1330                 ilg.Br(ilg.ReturnLabel);
1331             }
1332             ilg.EndIf();
1333
1334             ElementAccessor element = new ElementAccessor();
1335             element.Mapping = nullableMapping.BaseMapping;
1336             element.Any = false;
1337             element.IsNullable = nullableMapping.BaseMapping.TypeDesc.IsNullable;
1338
1339             WriteElement("o", null, null, element, null, null, false, false, -1, -1);
1340             ilg.Ldloc(oLoc);
1341             ilg.Stloc(ilg.ReturnLocal);
1342             ilg.Br(ilg.ReturnLabel);
1343
1344             ilg.MarkLabel(ilg.ReturnLabel);
1345             ilg.Ldloc(ilg.ReturnLocal);
1346             ilg.EndMethod();
1347         }
1348
1349         void WriteStructMethod(StructMapping structMapping) {
1350             WriteLiteralStructMethod(structMapping);
1351         }
1352
1353         void WriteLiteralStructMethod(StructMapping structMapping) {
1354             string methodName = (string)MethodNames[structMapping];
1355             string typeName = structMapping.TypeDesc.CSharpName;
1356             ilg = new CodeGenerator(this.typeBuilder);
1357             List<Type> argTypes = new List<Type>();
1358             List<string> argNames = new List<string>();
1359             if (structMapping.TypeDesc.IsNullable) {
1360                 argTypes.Add(typeof(Boolean));
1361                 argNames.Add("isNullable");
1362             }
1363             argTypes.Add(typeof(Boolean));
1364             argNames.Add("checkType");
1365             ilg.BeginMethod(
1366                 structMapping.TypeDesc.Type,
1367                 GetMethodBuilder(methodName),
1368                 argTypes.ToArray(),
1369                 argNames.ToArray(),
1370                 CodeGenerator.PrivateMethodAttributes);
1371
1372             LocalBuilder locXsiType = ilg.DeclareLocal(typeof(XmlQualifiedName), "xsiType");
1373             LocalBuilder locIsNull = ilg.DeclareLocal(typeof(Boolean), "isNull");
1374             MethodInfo XmlSerializationReader_GetXsiType = typeof(XmlSerializationReader).GetMethod(
1375                 "GetXsiType",
1376                 CodeGenerator.InstanceBindingFlags,
1377                 null,
1378                 CodeGenerator.EmptyTypeArray,
1379                 null
1380                 );
1381             MethodInfo XmlSerializationReader_ReadNull = typeof(XmlSerializationReader).GetMethod(
1382                  "ReadNull",
1383                  CodeGenerator.InstanceBindingFlags,
1384                  null,
1385                  CodeGenerator.EmptyTypeArray,
1386                  null
1387                  );
1388             Label labelTrue = ilg.DefineLabel();
1389             Label labelEnd = ilg.DefineLabel();
1390             ilg.Ldarg("checkType");
1391             ilg.Brtrue(labelTrue);
1392             ilg.Load(null);
1393             ilg.Br_S(labelEnd);
1394             ilg.MarkLabel(labelTrue);
1395             ilg.Ldarg(0);
1396             ilg.Call(XmlSerializationReader_GetXsiType);
1397             ilg.MarkLabel(labelEnd);
1398             ilg.Stloc(locXsiType);
1399             ilg.Ldc(false);
1400             ilg.Stloc(locIsNull);
1401             if (structMapping.TypeDesc.IsNullable) {
1402                 ilg.Ldarg("isNullable");
1403                 ilg.If();
1404                 {
1405                     ilg.Ldarg(0);
1406                     ilg.Call(XmlSerializationReader_ReadNull);
1407                     ilg.Stloc(locIsNull);
1408                 }
1409                 ilg.EndIf();
1410             }
1411
1412             ilg.Ldarg("checkType");
1413             ilg.If(); // if (checkType)
1414             if (structMapping.TypeDesc.IsRoot) {
1415                 ilg.Ldloc(locIsNull);
1416                 ilg.If();
1417                 ilg.Ldloc(locXsiType);
1418                 ilg.Load(null);
1419                 ilg.If(Cmp.NotEqualTo);
1420                 MethodInfo XmlSerializationReader_ReadTypedNull = typeof(XmlSerializationReader).GetMethod(
1421                        "ReadTypedNull",
1422                        CodeGenerator.InstanceBindingFlags,
1423                        null,
1424                        new Type[] { locXsiType.LocalType },
1425                        null
1426                        );
1427                 ilg.Ldarg(0);
1428                 ilg.Ldloc(locXsiType);
1429                 ilg.Call(XmlSerializationReader_ReadTypedNull);
1430                 ilg.Stloc(ilg.ReturnLocal);
1431                 ilg.Br(ilg.ReturnLabel);
1432                 ilg.Else();
1433                 if (structMapping.TypeDesc.IsValueType) {
1434                     throw CodeGenerator.NotSupported("Arg_NeverValueType");
1435                 }
1436                 else {
1437                     ilg.Load(null);
1438                     ilg.Stloc(ilg.ReturnLocal);
1439                     ilg.Br(ilg.ReturnLabel);
1440                 }
1441                 ilg.EndIf(); // if (xsiType != null)
1442
1443                 ilg.EndIf(); // if (isNull)
1444             }
1445             ilg.Ldloc(typeof(XmlQualifiedName), "xsiType");
1446             ilg.Load(null);
1447             ilg.Ceq();
1448             if (!structMapping.TypeDesc.IsRoot) {
1449                 labelTrue = ilg.DefineLabel();
1450                 labelEnd = ilg.DefineLabel();
1451                 // xsiType == null
1452                 ilg.Brtrue(labelTrue);
1453                 WriteQNameEqual("xsiType", structMapping.TypeName, structMapping.Namespace);
1454                 // Bool result for WriteQNameEqual is on the stack
1455                 ilg.Br_S(labelEnd);
1456                 ilg.MarkLabel(labelTrue);
1457                 ilg.Ldc(true);
1458                 ilg.MarkLabel(labelEnd);
1459             }
1460             ilg.If(); // if (xsiType == null
1461             if (structMapping.TypeDesc.IsRoot) {
1462                 ConstructorInfo XmlQualifiedName_ctor = typeof(XmlQualifiedName).GetConstructor(
1463                     CodeGenerator.InstanceBindingFlags,
1464                     null,
1465                     new Type[] { typeof(String), typeof(String) },
1466                     null
1467                     );
1468                 MethodInfo XmlSerializationReader_ReadTypedPrimitive = typeof(XmlSerializationReader).GetMethod(
1469                     "ReadTypedPrimitive",
1470                     CodeGenerator.InstanceBindingFlags,
1471                     null,
1472                     new Type[] { typeof(XmlQualifiedName) },
1473                     null
1474                     );
1475                 ilg.Ldarg(0);
1476                 ilg.Ldstr(Soap.UrType);
1477                 ilg.Ldstr(XmlSchema.Namespace);
1478                 ilg.New(XmlQualifiedName_ctor);
1479                 ilg.Call(XmlSerializationReader_ReadTypedPrimitive);
1480                 ilg.Stloc(ilg.ReturnLocal);
1481                 ilg.Br(ilg.ReturnLabel);
1482             }
1483             WriteDerivedTypes(structMapping, !structMapping.TypeDesc.IsRoot, typeName);
1484             if (structMapping.TypeDesc.IsRoot) WriteEnumAndArrayTypes();
1485             ilg.Else(); // if (xsiType == null
1486             if (structMapping.TypeDesc.IsRoot) {
1487                 MethodInfo XmlSerializationReader_ReadTypedPrimitive = typeof(XmlSerializationReader).GetMethod(
1488                     "ReadTypedPrimitive",
1489                     CodeGenerator.InstanceBindingFlags,
1490                     null,
1491                     new Type[] { locXsiType.LocalType },
1492                     null
1493                     );
1494                 ilg.Ldarg(0);
1495                 ilg.Ldloc(locXsiType);
1496                 ilg.Call(XmlSerializationReader_ReadTypedPrimitive);
1497                 ilg.Stloc(ilg.ReturnLocal);
1498                 ilg.Br(ilg.ReturnLabel);
1499             }
1500             else {
1501                 MethodInfo XmlSerializationReader_CreateUnknownTypeException = typeof(XmlSerializationReader).GetMethod(
1502                      "CreateUnknownTypeException",
1503                      CodeGenerator.InstanceBindingFlags,
1504                      null,
1505                      new Type[] { typeof(XmlQualifiedName) },
1506                      null
1507                      );
1508                 ilg.Ldarg(0);
1509                 ilg.Ldloc(locXsiType);
1510                 ilg.Call(XmlSerializationReader_CreateUnknownTypeException);
1511                 ilg.Throw();
1512             }
1513             ilg.EndIf(); // if (xsiType == null
1514             ilg.EndIf();  // checkType
1515
1516             if (structMapping.TypeDesc.IsNullable) {
1517                 ilg.Ldloc(typeof(bool), "isNull");
1518                 ilg.If();
1519                 {
1520                     ilg.Load(null);
1521                     ilg.Stloc(ilg.ReturnLocal);
1522                     ilg.Br(ilg.ReturnLabel);
1523                 }
1524                 ilg.EndIf();
1525             }
1526
1527             if (structMapping.TypeDesc.IsAbstract) {
1528                 MethodInfo XmlSerializationReader_CreateAbstractTypeException = typeof(XmlSerializationReader).GetMethod(
1529                     "CreateAbstractTypeException",
1530                     CodeGenerator.InstanceBindingFlags,
1531                     null,
1532                     new Type[] { typeof(String), typeof(String) },
1533                     null
1534                     );
1535                 ilg.Ldarg(0);
1536                 ilg.Ldstr(structMapping.TypeName);
1537                 ilg.Ldstr(structMapping.Namespace);
1538                 ilg.Call(XmlSerializationReader_CreateAbstractTypeException);
1539                 ilg.Throw();
1540             }
1541             else {
1542                 if (structMapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(structMapping.TypeDesc.Type)) {
1543                     MethodInfo XmlSerializationReader_set_DecodeName = typeof(XmlSerializationReader).GetMethod(
1544                          "set_DecodeName",
1545                          CodeGenerator.InstanceBindingFlags,
1546                          null,
1547                          new Type[] { typeof(Boolean) },
1548                          null
1549                          );
1550                     ilg.Ldarg(0);
1551                     ilg.Ldc(false);
1552                     ilg.Call(XmlSerializationReader_set_DecodeName);
1553                 }
1554                 WriteCreateMapping(structMapping, "o");
1555                 LocalBuilder oLoc = ilg.GetLocal("o");
1556
1557                 // this method populates the memberInfos dictionary based on the structMapping
1558                 MemberMapping[] mappings = TypeScope.GetSettableMembers(structMapping, memberInfos);
1559
1560                 Member anyText = null;
1561                 Member anyElement = null;
1562                 Member anyAttribute = null;
1563                 bool isSequence = structMapping.HasExplicitSequence();
1564
1565                 ArrayList arraysToDeclareList = new ArrayList(mappings.Length);
1566                 ArrayList arraysToSetList = new ArrayList(mappings.Length);
1567                 ArrayList allMembersList = new ArrayList(mappings.Length);
1568
1569                 for (int i = 0; i < mappings.Length; i++) {
1570                     MemberMapping mapping = mappings[i];
1571                     CodeIdentifier.CheckValidIdentifier(mapping.Name);
1572                     string source = RaCodeGen.GetStringForMember("o", mapping.Name, structMapping.TypeDesc);
1573                     Member member = new Member(this, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
1574                     if (!mapping.IsSequence)
1575                         member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
1576                     member.IsNullable = mapping.TypeDesc.IsNullable;
1577                     if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite)
1578                         member.CheckSpecifiedSource = RaCodeGen.GetStringForMember("o", mapping.Name + "Specified", structMapping.TypeDesc);
1579                     if (mapping.Text != null)
1580                         anyText = member;
1581                     if (mapping.Attribute != null && mapping.Attribute.Any)
1582                         anyAttribute = member;
1583                     if (!isSequence) {
1584                         // find anyElement if present.
1585                         for (int j = 0; j < mapping.Elements.Length; j++) {
1586                             if (mapping.Elements[j].Any && (mapping.Elements[j].Name == null || mapping.Elements[j].Name.Length == 0)) {
1587                                 anyElement = member;
1588                                 break;
1589                             }
1590                         }
1591                     }
1592                     else if (mapping.IsParticle && !mapping.IsSequence) {
1593                         StructMapping declaringMapping;
1594                         structMapping.FindDeclaringMapping(mapping, out declaringMapping, structMapping.TypeName);
1595                         throw new InvalidOperationException(Res.GetString(Res.XmlSequenceHierarchy, structMapping.TypeDesc.FullName, mapping.Name, declaringMapping.TypeDesc.FullName, "Order"));
1596                     }
1597                     if (mapping.Attribute == null && mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping) {
1598                         Member arrayMember = new Member(this, source, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
1599                         arrayMember.CheckSpecifiedSource = member.CheckSpecifiedSource;
1600                         allMembersList.Add(arrayMember);
1601                     }
1602                     else {
1603                         allMembersList.Add(member);
1604                     }
1605
1606                     if (mapping.TypeDesc.IsArrayLike) {
1607                         arraysToDeclareList.Add(member);
1608                         if (mapping.TypeDesc.IsArrayLike && !(mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping)) {
1609                             member.ParamsReadSource = null; // flat arrays -- don't want to count params read.
1610                             if (member != anyText && member != anyElement) {
1611                                 arraysToSetList.Add(member);
1612                             }
1613                         }
1614                         else if (!mapping.TypeDesc.IsArray) {
1615                             member.ParamsReadSource = null; // collection
1616                         }
1617                     }
1618                 }
1619                 if (anyElement != null) arraysToSetList.Add(anyElement);
1620                 if (anyText != null && anyText != anyElement) arraysToSetList.Add(anyText);
1621
1622                 Member[] arraysToDeclare = (Member[])arraysToDeclareList.ToArray(typeof(Member));
1623                 Member[] arraysToSet = (Member[])arraysToSetList.ToArray(typeof(Member));
1624                 Member[] allMembers = (Member[])allMembersList.ToArray(typeof(Member));
1625
1626                 WriteMemberBegin(arraysToDeclare);
1627                 WriteParamsRead(mappings.Length);
1628
1629                 WriteAttributes(allMembers, anyAttribute, "UnknownNode", oLoc);
1630                 if (anyAttribute != null)
1631                     WriteMemberEnd(arraysToDeclare);
1632
1633                 MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
1634                     "get_Reader",
1635                     CodeGenerator.InstanceBindingFlags,
1636                     null,
1637                     CodeGenerator.EmptyTypeArray,
1638                     null
1639                     );
1640                 MethodInfo XmlReader_MoveToElement = typeof(XmlReader).GetMethod(
1641                     "MoveToElement",
1642                     CodeGenerator.InstanceBindingFlags,
1643                     null,
1644                     CodeGenerator.EmptyTypeArray,
1645                     null
1646                     );
1647                 ilg.Ldarg(0);
1648                 ilg.Call(XmlSerializationReader_get_Reader);
1649                 ilg.Call(XmlReader_MoveToElement);
1650                 ilg.Pop();
1651
1652                 MethodInfo XmlReader_get_IsEmptyElement = typeof(XmlReader).GetMethod(
1653                     "get_IsEmptyElement",
1654                     CodeGenerator.InstanceBindingFlags,
1655                     null,
1656                     CodeGenerator.EmptyTypeArray,
1657                     null
1658                     );
1659                 ilg.Ldarg(0);
1660                 ilg.Call(XmlSerializationReader_get_Reader);
1661                 ilg.Call(XmlReader_get_IsEmptyElement);
1662                 ilg.If();
1663                 MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
1664                     "Skip",
1665                     CodeGenerator.InstanceBindingFlags,
1666                     null,
1667                     CodeGenerator.EmptyTypeArray,
1668                     null
1669                     );
1670                 ilg.Ldarg(0);
1671                 ilg.Call(XmlSerializationReader_get_Reader);
1672                 ilg.Call(XmlReader_Skip);
1673                 WriteMemberEnd(arraysToSet);
1674                 ilg.Ldloc(oLoc);
1675                 ilg.Stloc(ilg.ReturnLocal);
1676                 ilg.Br(ilg.ReturnLabel);
1677                 ilg.EndIf();
1678
1679                 MethodInfo XmlReader_ReadStartElement = typeof(XmlReader).GetMethod(
1680                     "ReadStartElement",
1681                     CodeGenerator.InstanceBindingFlags,
1682                     null,
1683                     CodeGenerator.EmptyTypeArray,
1684                     null
1685                     );
1686                 ilg.Ldarg(0);
1687                 ilg.Call(XmlSerializationReader_get_Reader);
1688                 ilg.Call(XmlReader_ReadStartElement);
1689                 if (IsSequence(allMembers)) {
1690                     ilg.Ldc(0);
1691                     ilg.Stloc(typeof(Int32), "state");
1692                 }
1693                 int loopIndex = WriteWhileNotLoopStart();
1694                 string unknownNode = "UnknownNode((object)o, " + ExpectedElements(allMembers) + ");";
1695                 WriteMemberElements(allMembers, unknownNode, unknownNode, anyElement, anyText);
1696                 MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
1697                     "MoveToContent",
1698                     CodeGenerator.InstanceBindingFlags,
1699                     null,
1700                     CodeGenerator.EmptyTypeArray,
1701                     null
1702                     );
1703                 ilg.Ldarg(0);
1704                 ilg.Call(XmlSerializationReader_get_Reader);
1705                 ilg.Call(XmlReader_MoveToContent);
1706                 ilg.Pop();
1707
1708                 WriteWhileLoopEnd(loopIndex);
1709                 WriteMemberEnd(arraysToSet);
1710
1711                 MethodInfo XmlSerializationReader_ReadEndElement = typeof(XmlSerializationReader).GetMethod(
1712                     "ReadEndElement",
1713                     CodeGenerator.InstanceBindingFlags,
1714                     null,
1715                     CodeGenerator.EmptyTypeArray,
1716                     null
1717                     );
1718                 ilg.Ldarg(0);
1719                 ilg.Call(XmlSerializationReader_ReadEndElement);
1720                 ilg.Ldloc(structMapping.TypeDesc.Type, "o");
1721                 ilg.Stloc(ilg.ReturnLocal);
1722             }
1723             ilg.MarkLabel(ilg.ReturnLabel);
1724             ilg.Ldloc(ilg.ReturnLocal);
1725             ilg.EndMethod();
1726         }
1727
1728         void WriteQNameEqual(string source, string name, string ns) {
1729             WriteID(name);
1730             WriteID(ns);
1731             // This api assume the source is local member of XmlQualifiedName type
1732             // It leaves bool result on the stack
1733             MethodInfo XmlQualifiedName_get_Name = typeof(XmlQualifiedName).GetMethod(
1734                 "get_Name",
1735                 CodeGenerator.InstanceBindingFlags,
1736                 null,
1737                 CodeGenerator.EmptyTypeArray,
1738                 null
1739                 );
1740             MethodInfo XmlQualifiedName_get_Namespace = typeof(XmlQualifiedName).GetMethod(
1741                 "get_Namespace",
1742                 CodeGenerator.InstanceBindingFlags,
1743                 null,
1744                 CodeGenerator.EmptyTypeArray,
1745                 null
1746                 );
1747             Label labelEnd = ilg.DefineLabel();
1748             Label labelFalse = ilg.DefineLabel();
1749             LocalBuilder sLoc = ilg.GetLocal(source);
1750             ilg.Ldloc(sLoc);
1751             ilg.Call(XmlQualifiedName_get_Name);
1752             ilg.Ldarg(0);
1753             ilg.LoadMember(idNameFields[name ?? String.Empty]);
1754             ilg.Bne(labelFalse);
1755             ilg.Ldloc(sLoc);
1756             ilg.Call(XmlQualifiedName_get_Namespace);
1757             ilg.Ldarg(0);
1758             ilg.LoadMember(idNameFields[ns ?? String.Empty]);
1759             ilg.Ceq();
1760             ilg.Br_S(labelEnd);
1761             ilg.MarkLabel(labelFalse);
1762             ilg.Ldc(false);
1763             ilg.MarkLabel(labelEnd);
1764         }
1765
1766         void WriteXmlNodeEqual(string source, string name, string ns) {
1767             WriteXmlNodeEqual(source, name, ns, true);
1768         }
1769         void WriteXmlNodeEqual(string source, string name, string ns, bool doAndIf) {
1770             bool isNameNullOrEmpty = string.IsNullOrEmpty(name);
1771             if (!isNameNullOrEmpty) {
1772                 WriteID(name);
1773             }
1774             WriteID(ns);
1775             // Only support Reader and XmlSerializationReaderReader only
1776             System.Diagnostics.Debug.Assert(source == "Reader");
1777             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
1778                 "get_" + source,
1779                 CodeGenerator.InstanceBindingFlags,
1780                 null,
1781                 CodeGenerator.EmptyTypeArray,
1782                 null
1783                 );
1784             MethodInfo XmlReader_get_LocalName = typeof(XmlReader).GetMethod(
1785                 "get_LocalName",
1786                 CodeGenerator.InstanceBindingFlags,
1787                 null,
1788                 CodeGenerator.EmptyTypeArray,
1789                 null
1790                 );
1791             MethodInfo XmlReader_get_NamespaceURI = typeof(XmlReader).GetMethod(
1792                 "get_NamespaceURI",
1793                 CodeGenerator.InstanceBindingFlags,
1794                 null,
1795                 CodeGenerator.EmptyTypeArray,
1796                 null
1797                 );
1798
1799             Label labelFalse = ilg.DefineLabel();
1800             Label labelEnd = ilg.DefineLabel();
1801
1802             if (!isNameNullOrEmpty) {
1803                 ilg.Ldarg(0);
1804                 ilg.Call(XmlSerializationReader_get_Reader);
1805                 ilg.Call(XmlReader_get_LocalName);
1806                 ilg.Ldarg(0);
1807                 ilg.LoadMember(idNameFields[name ?? String.Empty]);
1808                 ilg.Bne(labelFalse);
1809             }
1810
1811             ilg.Ldarg(0);
1812             ilg.Call(XmlSerializationReader_get_Reader);
1813             ilg.Call(XmlReader_get_NamespaceURI);
1814             ilg.Ldarg(0);
1815             ilg.LoadMember(idNameFields[ns ?? String.Empty]);
1816             ilg.Ceq();
1817
1818             if (!isNameNullOrEmpty) {
1819                 ilg.Br_S(labelEnd);
1820                 ilg.MarkLabel(labelFalse);
1821                 ilg.Ldc(false);
1822                 ilg.MarkLabel(labelEnd);
1823             }
1824             if (doAndIf)
1825                 ilg.AndIf();
1826         }
1827
1828         void WriteID(string name) {
1829             if (name == null) {
1830                 //Writer.Write("null");
1831                 //return;
1832                 name = "";
1833             }
1834             string idName = (string)idNames[name];
1835             if (idName == null) {
1836                 idName = NextIdName(name);
1837                 idNames.Add(name, idName);
1838                 idNameFields.Add(name, this.typeBuilder.DefineField(idName, typeof(string), FieldAttributes.Private));
1839             }
1840         }
1841
1842         void WriteAttributes(Member[] members, Member anyAttribute, string elseCall, LocalBuilder firstParam) {
1843             int count = 0;
1844             Member xmlnsMember = null;
1845             ArrayList attributes = new ArrayList();
1846
1847             // Condition do at the end, so C# looks the same
1848             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
1849                 "get_Reader",
1850                 CodeGenerator.InstanceBindingFlags,
1851                 null,
1852                 CodeGenerator.EmptyTypeArray,
1853                 null
1854                 );
1855             MethodInfo XmlReader_MoveToNextAttribute = typeof(XmlReader).GetMethod(
1856                 "MoveToNextAttribute",
1857                 CodeGenerator.InstanceBindingFlags,
1858                 null,
1859                 CodeGenerator.EmptyTypeArray,
1860                 null
1861                 );
1862             ilg.WhileBegin();
1863
1864             for (int i = 0; i < members.Length; i++) {
1865                 Member member = (Member)members[i];
1866                 if (member.Mapping.Xmlns != null) {
1867                     xmlnsMember = member;
1868                     continue;
1869                 }
1870                 if (member.Mapping.Ignore)
1871                     continue;
1872                 AttributeAccessor attribute = member.Mapping.Attribute;
1873
1874                 if (attribute == null) continue;
1875                 if (attribute.Any) continue;
1876
1877                 attributes.Add(attribute);
1878
1879                 if (count++ > 0)
1880                     ilg.InitElseIf();
1881                 else
1882                     ilg.InitIf();
1883
1884                 if (member.ParamsReadSource != null) {
1885                     ILGenParamsReadSource(member.ParamsReadSource);
1886                     ilg.Ldc(false);
1887                     ilg.AndIf(Cmp.EqualTo);
1888                 }
1889
1890                 if (attribute.IsSpecialXmlNamespace) {
1891                     WriteXmlNodeEqual("Reader", attribute.Name, XmlReservedNs.NsXml);
1892                 }
1893                 else
1894                     WriteXmlNodeEqual("Reader", attribute.Name, attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "");
1895
1896                 WriteAttribute(member);
1897             }
1898
1899             if (count > 0)
1900                 ilg.InitElseIf();
1901             else
1902                 ilg.InitIf();
1903
1904             if (xmlnsMember != null) {
1905                 MethodInfo XmlSerializationReader_IsXmlnsAttribute = typeof(XmlSerializationReader).GetMethod(
1906                     "IsXmlnsAttribute",
1907                     CodeGenerator.InstanceBindingFlags,
1908                     null,
1909                     new Type[] { typeof(string) },
1910                     null
1911                     );
1912                 MethodInfo XmlReader_get_Name = typeof(XmlReader).GetMethod(
1913                     "get_Name",
1914                     CodeGenerator.InstanceBindingFlags,
1915                     null,
1916                     CodeGenerator.EmptyTypeArray,
1917                     null
1918                     );
1919                 MethodInfo XmlReader_get_LocalName = typeof(XmlReader).GetMethod(
1920                     "get_LocalName",
1921                     CodeGenerator.InstanceBindingFlags,
1922                     null,
1923                     CodeGenerator.EmptyTypeArray,
1924                     null
1925                     );
1926                 MethodInfo XmlReader_get_Value = typeof(XmlReader).GetMethod(
1927                     "get_Value",
1928                     CodeGenerator.InstanceBindingFlags,
1929                     null,
1930                     CodeGenerator.EmptyTypeArray,
1931                     null
1932                     );
1933                 ilg.Ldarg(0);
1934                 ilg.Ldarg(0);
1935                 ilg.Call(XmlSerializationReader_get_Reader);
1936                 ilg.Call(XmlReader_get_Name);
1937                 ilg.Call(XmlSerializationReader_IsXmlnsAttribute);
1938                 ilg.Ldc(true);
1939                 ilg.AndIf(Cmp.EqualTo);
1940
1941                 ILGenLoad(xmlnsMember.Source);
1942                 ilg.Load(null);
1943                 ilg.If(Cmp.EqualTo);
1944                 WriteSourceBegin(xmlnsMember.Source);
1945                 ConstructorInfo ctor = xmlnsMember.Mapping.TypeDesc.Type.GetConstructor(
1946                     CodeGenerator.InstanceBindingFlags,
1947                     null,
1948                     CodeGenerator.EmptyTypeArray,
1949                     null
1950                     );
1951                 ilg.New(ctor);
1952                 WriteSourceEnd(xmlnsMember.Source, xmlnsMember.Mapping.TypeDesc.Type);
1953                 ilg.EndIf(); // if (xmlnsMember.Source == null
1954
1955                 Label labelEqual5 = ilg.DefineLabel();
1956                 Label labelEndLength = ilg.DefineLabel();
1957                 MethodInfo Add = xmlnsMember.Mapping.TypeDesc.Type.GetMethod(
1958                     "Add",
1959                     CodeGenerator.InstanceBindingFlags,
1960                     null,
1961                     new Type[] { typeof(String), typeof(String) },
1962                     null
1963                     );
1964                 MethodInfo String_get_Length = typeof(String).GetMethod(
1965                     "get_Length",
1966                     CodeGenerator.InstanceBindingFlags,
1967                     null,
1968                     CodeGenerator.EmptyTypeArray,
1969                     null
1970                     );
1971                 ILGenLoad(xmlnsMember.ArraySource, xmlnsMember.Mapping.TypeDesc.Type);
1972                 ilg.Ldarg(0);
1973                 ilg.Call(XmlSerializationReader_get_Reader);
1974                 ilg.Call(XmlReader_get_Name);
1975                 ilg.Call(String_get_Length);
1976                 ilg.Ldc(5);
1977                 ilg.Beq(labelEqual5);
1978                 ilg.Ldarg(0);
1979                 ilg.Call(XmlSerializationReader_get_Reader);
1980                 ilg.Call(XmlReader_get_LocalName);
1981                 ilg.Br(labelEndLength);
1982                 ilg.MarkLabel(labelEqual5);
1983                 ilg.Ldstr(String.Empty);
1984                 ilg.MarkLabel(labelEndLength);
1985                 ilg.Ldarg(0);
1986                 ilg.Call(XmlSerializationReader_get_Reader);
1987                 ilg.Call(XmlReader_get_Value);
1988                 ilg.Call(Add);
1989
1990                 ilg.Else();
1991             }
1992             else {
1993                 MethodInfo XmlSerializationReader_IsXmlnsAttribute = typeof(XmlSerializationReader).GetMethod(
1994                     "IsXmlnsAttribute",
1995                     CodeGenerator.InstanceBindingFlags,
1996                     null,
1997                     new Type[] { typeof(string) },
1998                     null
1999                     );
2000                 MethodInfo XmlReader_get_Name = typeof(XmlReader).GetMethod(
2001                     "get_Name",
2002                     CodeGenerator.InstanceBindingFlags,
2003                     null,
2004                     CodeGenerator.EmptyTypeArray,
2005                     null
2006                     );
2007                 ilg.Ldarg(0);
2008                 ilg.Ldarg(0);
2009                 ilg.Call(XmlSerializationReader_get_Reader);
2010                 ilg.Call(XmlReader_get_Name);
2011                 ilg.Call(XmlSerializationReader_IsXmlnsAttribute);
2012                 ilg.Ldc(false);
2013                 ilg.AndIf(Cmp.EqualTo);
2014             }
2015             if (anyAttribute != null) {
2016                 LocalBuilder localAttr = ilg.DeclareOrGetLocal(typeof(XmlAttribute), "attr");
2017                 MethodInfo XmlSerializationReader_get_Document = typeof(XmlSerializationReader).GetMethod(
2018                     "get_Document",
2019                     CodeGenerator.InstanceBindingFlags,
2020                     null,
2021                     CodeGenerator.EmptyTypeArray,
2022                     null
2023                     );
2024                 MethodInfo XmlDocument_ReadNode = typeof(XmlDocument).GetMethod(
2025                     "ReadNode",
2026                     CodeGenerator.InstanceBindingFlags,
2027                     null,
2028                     new Type[] { typeof(XmlReader) },
2029                     null
2030                     );
2031                 ilg.Ldarg(0);
2032                 ilg.Call(XmlSerializationReader_get_Document);
2033                 ilg.Ldarg(0);
2034                 ilg.Call(XmlSerializationReader_get_Reader);
2035                 ilg.Call(XmlDocument_ReadNode);
2036                 ilg.ConvertValue(XmlDocument_ReadNode.ReturnType, localAttr.LocalType);
2037                 ilg.Stloc(localAttr);
2038                 MethodInfo XmlSerializationReader_ParseWsdlArrayType = typeof(XmlSerializationReader).GetMethod(
2039                     "ParseWsdlArrayType",
2040                     CodeGenerator.InstanceBindingFlags,
2041                     null,
2042                     new Type[] { localAttr.LocalType },
2043                     null
2044                     );
2045                 ilg.Ldarg(0);
2046                 ilg.Ldloc(localAttr);
2047                 ilg.Call(XmlSerializationReader_ParseWsdlArrayType);
2048                 WriteAttribute(anyAttribute);
2049             }
2050             else {
2051                 List<Type> argTypes = new List<Type>();
2052                 ilg.Ldarg(0);
2053                 argTypes.Add(typeof(object));
2054                 ilg.Ldloc(firstParam);
2055                 ilg.ConvertValue(firstParam.LocalType, typeof(object));
2056                 if (attributes.Count > 0) {
2057                     string qnames = "";
2058
2059                     for (int i = 0; i < attributes.Count; i++) {
2060                         AttributeAccessor attribute = (AttributeAccessor)attributes[i];
2061                         if (i > 0)
2062                             qnames += ", ";
2063                         qnames += attribute.IsSpecialXmlNamespace ? XmlReservedNs.NsXml : (attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "") + ":" + attribute.Name;
2064                     }
2065                     argTypes.Add(typeof(string));
2066                     ilg.Ldstr(qnames);
2067                 }
2068                 System.Diagnostics.Debug.Assert(elseCall == "UnknownNode");
2069                 MethodInfo elseCallMethod = typeof(XmlSerializationReader).GetMethod(
2070                     elseCall,
2071                     CodeGenerator.InstanceBindingFlags,
2072                     null,
2073                     argTypes.ToArray(),
2074                     null
2075                     );
2076                 ilg.Call(elseCallMethod);
2077             }
2078             ilg.EndIf();
2079
2080             ilg.WhileBeginCondition();
2081             {
2082                 ilg.Ldarg(0);
2083                 ilg.Call(XmlSerializationReader_get_Reader);
2084                 ilg.Call(XmlReader_MoveToNextAttribute);
2085             }
2086             ilg.WhileEndCondition();
2087             ilg.WhileEnd();
2088         }
2089
2090         void WriteAttribute(Member member) {
2091
2092             AttributeAccessor attribute = member.Mapping.Attribute;
2093
2094             if (attribute.Mapping is SpecialMapping) {
2095                 SpecialMapping special = (SpecialMapping)attribute.Mapping;
2096
2097                 if (special.TypeDesc.Kind == TypeKind.Attribute) {
2098                     WriteSourceBegin(member.ArraySource);
2099                     ilg.Ldloc("attr");
2100                     WriteSourceEnd(member.ArraySource, member.Mapping.TypeDesc.IsArrayLike ? member.Mapping.TypeDesc.ArrayElementTypeDesc.Type : member.Mapping.TypeDesc.Type);
2101                 }
2102                 else if (special.TypeDesc.CanBeAttributeValue) {
2103                     LocalBuilder attrLoc = ilg.GetLocal("attr");
2104                     ilg.Ldloc(attrLoc);
2105                     // to get code compat
2106                     if (attrLoc.LocalType == typeof(XmlAttribute)) {
2107                         ilg.Load(null);
2108                         ilg.Cne();
2109                     }
2110                     else
2111                         ilg.IsInst(typeof(XmlAttribute));
2112                     ilg.If();
2113                     WriteSourceBegin(member.ArraySource);
2114                     ilg.Ldloc(attrLoc);
2115                     ilg.ConvertValue(attrLoc.LocalType, typeof(XmlAttribute));
2116                     WriteSourceEnd(member.ArraySource, member.Mapping.TypeDesc.IsArrayLike ? member.Mapping.TypeDesc.ArrayElementTypeDesc.Type : member.Mapping.TypeDesc.Type);
2117                     ilg.EndIf();
2118                 }
2119                 else
2120                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
2121             }
2122             else {
2123                 if (attribute.IsList) {
2124                     LocalBuilder locListValues = ilg.DeclareOrGetLocal(typeof(string), "listValues");
2125                     LocalBuilder locVals = ilg.DeclareOrGetLocal(typeof(string[]), "vals");
2126                     MethodInfo String_Split = typeof(String).GetMethod(
2127                         "Split",
2128                         CodeGenerator.InstanceBindingFlags,
2129                         null,
2130                         new Type[] { typeof(Char[]) },
2131                         null
2132                         );
2133                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2134                         "get_Reader",
2135                         CodeGenerator.InstanceBindingFlags,
2136                         null,
2137                         CodeGenerator.EmptyTypeArray,
2138                         null
2139                         );
2140                     MethodInfo XmlReader_get_Value = typeof(XmlReader).GetMethod(
2141                         "get_Value",
2142                         CodeGenerator.InstanceBindingFlags,
2143                         null,
2144                         CodeGenerator.EmptyTypeArray,
2145                         null
2146                         );
2147                     ilg.Ldarg(0);
2148                     ilg.Call(XmlSerializationReader_get_Reader);
2149                     ilg.Call(XmlReader_get_Value);
2150                     ilg.Stloc(locListValues);
2151                     ilg.Ldloc(locListValues);
2152                     ilg.Load(null);
2153                     ilg.Call(String_Split);
2154                     ilg.Stloc(locVals);
2155                     LocalBuilder localI = ilg.DeclareOrGetLocal(typeof(Int32), "i");
2156                     ilg.For(localI, 0, locVals);
2157
2158                     string attributeSource = GetArraySource(member.Mapping.TypeDesc, member.ArrayName);
2159
2160                     WriteSourceBegin(attributeSource);
2161                     WritePrimitive(attribute.Mapping, "vals[i]");
2162                     WriteSourceEnd(attributeSource, member.Mapping.TypeDesc.ArrayElementTypeDesc.Type);
2163                     ilg.EndFor();
2164                 }
2165                 else {
2166                     WriteSourceBegin(member.ArraySource);
2167                     WritePrimitive(attribute.Mapping, attribute.IsList ? "vals[i]" : "Reader.Value");
2168                     WriteSourceEnd(member.ArraySource, member.Mapping.TypeDesc.IsArrayLike ? member.Mapping.TypeDesc.ArrayElementTypeDesc.Type : member.Mapping.TypeDesc.Type);
2169                 }
2170             }
2171             if (member.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite && member.CheckSpecifiedSource != null && member.CheckSpecifiedSource.Length > 0) {
2172                 ILGenSet(member.CheckSpecifiedSource, true);
2173             }
2174             if (member.ParamsReadSource != null) {
2175                 ILGenParamsReadSource(member.ParamsReadSource, true);
2176             }
2177         }
2178
2179         void WriteMemberBegin(Member[] members) {
2180
2181             for (int i = 0; i < members.Length; i++) {
2182                 Member member = (Member)members[i];
2183
2184                 if (member.IsArrayLike) {
2185                     string a = member.ArrayName;
2186                     string c = "c" + a;
2187
2188                     TypeDesc typeDesc = member.Mapping.TypeDesc;
2189
2190                     if (member.Mapping.TypeDesc.IsArray) {
2191                         WriteArrayLocalDecl(typeDesc.CSharpName,
2192                                             a, "null", typeDesc);
2193                         ilg.Ldc(0);
2194                         ilg.Stloc(typeof(int), c);
2195
2196                         if (member.Mapping.ChoiceIdentifier != null) {
2197                             WriteArrayLocalDecl(member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.CSharpName + "[]",
2198                                                 member.ChoiceArrayName, "null",
2199                                                 member.Mapping.ChoiceIdentifier.Mapping.TypeDesc);
2200                             ilg.Ldc(0);
2201                             ilg.Stloc(typeof(int), "c" + member.ChoiceArrayName);
2202
2203                         }
2204                     }
2205                     else {
2206                         if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{') {
2207                             WriteCreateInstance(a, typeDesc.CannotNew, typeDesc.Type);
2208                             WriteSourceBegin(member.Source);
2209                             ilg.Ldloc(ilg.GetLocal(a));
2210                             WriteSourceEnd(member.Source, typeDesc.Type);
2211                         }
2212                         else {
2213                             if (member.IsList && !member.Mapping.ReadOnly && member.Mapping.TypeDesc.IsNullable) {
2214                                 // we need to new the Collections and ArrayLists
2215                                 ILGenLoad(member.Source, typeof(object));
2216                                 ilg.Load(null);
2217                                 ilg.If(Cmp.EqualTo);
2218                                 if (!member.Mapping.TypeDesc.HasDefaultConstructor) {
2219                                     MethodInfo XmlSerializationReader_CreateReadOnlyCollectionException = typeof(XmlSerializationReader).GetMethod(
2220                                          "CreateReadOnlyCollectionException",
2221                                          CodeGenerator.InstanceBindingFlags,
2222                                          null,
2223                                          new Type[] { typeof(String) },
2224                                          null
2225                                          );
2226                                     ilg.Ldarg(0);
2227                                     ilg.Ldstr(member.Mapping.TypeDesc.CSharpName);
2228                                     ilg.Call(XmlSerializationReader_CreateReadOnlyCollectionException);
2229                                     ilg.Throw();
2230                                 }
2231                                 else {
2232                                     WriteSourceBegin(member.Source);
2233                                     RaCodeGen.ILGenForCreateInstance(ilg, member.Mapping.TypeDesc.Type, typeDesc.CannotNew, true);
2234                                     WriteSourceEnd(member.Source, member.Mapping.TypeDesc.Type);
2235                                 }
2236                                 ilg.EndIf(); // if ((object)(member.Source) == null
2237                             }
2238                             WriteLocalDecl(a, new SourceInfo(member.Source, member.Source, member.Mapping.MemberInfo, member.Mapping.TypeDesc.Type, ilg));
2239                         }
2240                     }
2241                 }
2242             }
2243         }
2244
2245         string ExpectedElements(Member[] members) {
2246             if (IsSequence(members))
2247                 return "null";
2248             string qnames = string.Empty;
2249             bool firstElement = true;
2250             for (int i = 0; i < members.Length; i++) {
2251                 Member member = (Member)members[i];
2252                 if (member.Mapping.Xmlns != null)
2253                     continue;
2254                 if (member.Mapping.Ignore)
2255                     continue;
2256                 if (member.Mapping.IsText || member.Mapping.IsAttribute)
2257                     continue;
2258
2259                 ElementAccessor[] elements = member.Mapping.Elements;
2260
2261                 for (int j = 0; j < elements.Length; j++) {
2262                     ElementAccessor e = elements[j];
2263                     string ns = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
2264                     if (e.Any && (e.Name == null || e.Name.Length == 0)) continue;
2265
2266                     if (!firstElement)
2267                         qnames += ", ";
2268                     qnames += ns + ":" + e.Name;
2269                     firstElement = false;
2270                 }
2271             }
2272             return ReflectionAwareILGen.GetQuotedCSharpString(null, qnames);
2273         }
2274
2275         void WriteMemberElements(Member[] members, string elementElseString, string elseString, Member anyElement, Member anyText) {
2276             if (anyText != null) {
2277                 ilg.Load(null);
2278                 ilg.Stloc(typeof(string), "tmp");
2279             }
2280
2281             MethodInfo XmlReader_get_NodeType = typeof(XmlReader).GetMethod(
2282                  "get_NodeType",
2283                  CodeGenerator.InstanceBindingFlags,
2284                  null,
2285                  CodeGenerator.EmptyTypeArray,
2286                  null
2287                  );
2288             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2289                 "get_Reader",
2290                 CodeGenerator.InstanceBindingFlags,
2291                 null,
2292                 CodeGenerator.EmptyTypeArray,
2293                 null
2294                 );
2295             int XmlNodeType_Element = 1;
2296             ilg.Ldarg(0);
2297             ilg.Call(XmlSerializationReader_get_Reader);
2298             ilg.Call(XmlReader_get_NodeType);
2299             ilg.Ldc(XmlNodeType_Element);
2300             ilg.If(Cmp.EqualTo);
2301
2302             WriteMemberElementsIf(members, anyElement, elementElseString);
2303
2304             if (anyText != null)
2305                 WriteMemberText(anyText, elseString);
2306
2307             ilg.Else();
2308             ILGenElseString(elseString);
2309             ilg.EndIf();
2310         }
2311
2312         void WriteMemberText(Member anyText, string elseString) {
2313             ilg.InitElseIf();
2314             Label labelTrue = ilg.DefineLabel();
2315             Label labelEnd = ilg.DefineLabel();
2316             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2317                 "get_Reader",
2318                 CodeGenerator.InstanceBindingFlags,
2319                 null,
2320                 CodeGenerator.EmptyTypeArray,
2321                 null
2322                 );
2323             MethodInfo XmlReader_get_NodeType = typeof(XmlReader).GetMethod(
2324                 "get_NodeType",
2325                 CodeGenerator.InstanceBindingFlags,
2326                 null,
2327                 CodeGenerator.EmptyTypeArray,
2328                 null
2329                 );
2330             ilg.Ldarg(0);
2331             ilg.Call(XmlSerializationReader_get_Reader);
2332             ilg.Call(XmlReader_get_NodeType);
2333             ilg.Ldc(XmlNodeType.Text);
2334             ilg.Ceq();
2335             ilg.Brtrue(labelTrue);
2336             ilg.Ldarg(0);
2337             ilg.Call(XmlSerializationReader_get_Reader);
2338             ilg.Call(XmlReader_get_NodeType);
2339             ilg.Ldc(XmlNodeType.CDATA);
2340             ilg.Ceq();
2341             ilg.Brtrue(labelTrue);
2342             ilg.Ldarg(0);
2343             ilg.Call(XmlSerializationReader_get_Reader);
2344             ilg.Call(XmlReader_get_NodeType);
2345             ilg.Ldc(XmlNodeType.Whitespace);
2346             ilg.Ceq();
2347             ilg.Brtrue(labelTrue);
2348             ilg.Ldarg(0);
2349             ilg.Call(XmlSerializationReader_get_Reader);
2350             ilg.Call(XmlReader_get_NodeType);
2351             ilg.Ldc(XmlNodeType.SignificantWhitespace);
2352             ilg.Ceq();
2353             ilg.Br(labelEnd);
2354             ilg.MarkLabel(labelTrue);
2355             ilg.Ldc(true);
2356             ilg.MarkLabel(labelEnd);
2357             ilg.AndIf();
2358
2359             if (anyText != null) {
2360                 WriteText(anyText);
2361             }
2362             Debug.Assert(anyText != null);
2363         }
2364
2365         void WriteText(Member member) {
2366
2367             TextAccessor text = member.Mapping.Text;
2368
2369             if (text.Mapping is SpecialMapping) {
2370                 SpecialMapping special = (SpecialMapping)text.Mapping;
2371                 WriteSourceBeginTyped(member.ArraySource, special.TypeDesc);
2372                 switch (special.TypeDesc.Kind) {
2373                     case TypeKind.Node:
2374                         MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2375                             "get_Reader",
2376                             CodeGenerator.InstanceBindingFlags,
2377                             null,
2378                             CodeGenerator.EmptyTypeArray,
2379                             null
2380                             );
2381                         MethodInfo XmlReader_ReadString = typeof(XmlReader).GetMethod(
2382                             "ReadString",
2383                             CodeGenerator.InstanceBindingFlags,
2384                             null,
2385                             CodeGenerator.EmptyTypeArray,
2386                             null
2387                             );
2388                         MethodInfo XmlSerializationReader_get_Document = typeof(XmlSerializationReader).GetMethod(
2389                             "get_Document",
2390                             CodeGenerator.InstanceBindingFlags,
2391                             null,
2392                             CodeGenerator.EmptyTypeArray,
2393                             null
2394                             );
2395                         MethodInfo XmlDocument_CreateTextNode = typeof(XmlDocument).GetMethod(
2396                             "CreateTextNode",
2397                             CodeGenerator.InstanceBindingFlags,
2398                             null,
2399                             new Type[] { typeof(String) },
2400                             null
2401                             );
2402                         ilg.Ldarg(0);
2403                         ilg.Call(XmlSerializationReader_get_Document);
2404                         ilg.Ldarg(0);
2405                         ilg.Call(XmlSerializationReader_get_Reader);
2406                         ilg.Call(XmlReader_ReadString);
2407                         ilg.Call(XmlDocument_CreateTextNode);
2408                         break;
2409                     default:
2410                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
2411                 }
2412                 WriteSourceEnd(member.ArraySource, special.TypeDesc.Type);
2413             }
2414             else {
2415                 if (member.IsArrayLike) {
2416                     WriteSourceBegin(member.ArraySource);
2417                     if (text.Mapping.TypeDesc.CollapseWhitespace) {
2418                         ilg.Ldarg(0); // for calling CollapseWhitespace
2419                     }
2420                     else {
2421                     }
2422                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2423                          "get_Reader",
2424                          CodeGenerator.InstanceBindingFlags,
2425                          null,
2426                          CodeGenerator.EmptyTypeArray,
2427                          null
2428                          );
2429                     MethodInfo XmlReader_ReadString = typeof(XmlReader).GetMethod(
2430                         "ReadString",
2431                         CodeGenerator.InstanceBindingFlags,
2432                         null,
2433                         CodeGenerator.EmptyTypeArray,
2434                         null
2435                         );
2436                     ilg.Ldarg(0);
2437                     ilg.Call(XmlSerializationReader_get_Reader);
2438                     ilg.Call(XmlReader_ReadString);
2439                     if (text.Mapping.TypeDesc.CollapseWhitespace) {
2440                         MethodInfo XmlSerializationReader_CollapseWhitespace = typeof(XmlSerializationReader).GetMethod(
2441                             "CollapseWhitespace",
2442                             CodeGenerator.InstanceBindingFlags,
2443                             null,
2444                             new Type[] { typeof(String) },
2445                             null
2446                             );
2447                         ilg.Call(XmlSerializationReader_CollapseWhitespace);
2448                     }
2449                 }
2450                 else {
2451                     if (text.Mapping.TypeDesc == StringTypeDesc || text.Mapping.TypeDesc.FormatterName == "String") {
2452                         LocalBuilder tmpLoc = ilg.GetLocal("tmp");
2453                         MethodInfo XmlSerializationReader_ReadString = typeof(XmlSerializationReader).GetMethod(
2454                             "ReadString",
2455                             CodeGenerator.InstanceBindingFlags,
2456                             null,
2457                             new Type[] { typeof(String), typeof(Boolean) },
2458                             null
2459                             );
2460                         ilg.Ldarg(0);
2461                         ilg.Ldloc(tmpLoc);
2462                         ilg.Ldc(text.Mapping.TypeDesc.CollapseWhitespace);
2463                         ilg.Call(XmlSerializationReader_ReadString);
2464                         ilg.Stloc(tmpLoc);
2465
2466                         WriteSourceBegin(member.ArraySource);
2467                         ilg.Ldloc(tmpLoc);
2468                     }
2469                     else {
2470                         WriteSourceBegin(member.ArraySource);
2471                         WritePrimitive(text.Mapping, "Reader.ReadString()");
2472                     }
2473                 }
2474                 WriteSourceEnd(member.ArraySource, text.Mapping.TypeDesc.Type);
2475             }
2476
2477         }
2478
2479
2480         void WriteMemberElementsElse(Member anyElement, string elementElseString) {
2481             if (anyElement != null) {
2482                 ElementAccessor[] elements = anyElement.Mapping.Elements;
2483                 for (int i = 0; i < elements.Length; i++) {
2484                     ElementAccessor element = elements[i];
2485                     if (element.Any && element.Name.Length == 0) {
2486                         WriteElement(anyElement.ArraySource, anyElement.ArrayName, anyElement.ChoiceArraySource, element, anyElement.Mapping.ChoiceIdentifier, anyElement.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite ? anyElement.CheckSpecifiedSource : null, false, false, -1, i);
2487                         break;
2488                     }
2489                 }
2490             }
2491             else {
2492                 ILGenElementElseString(elementElseString);
2493             }
2494         }
2495
2496         bool IsSequence(Member[] members) {
2497             for (int i = 0; i < members.Length; i++) {
2498                 if (members[i].Mapping.IsParticle && members[i].Mapping.IsSequence)
2499                     return true;
2500             }
2501             return false;
2502         }
2503         void WriteMemberElementsIf(Member[] members, Member anyElement, string elementElseString) {
2504             int count = 0;
2505
2506             bool isSequence = IsSequence(members);
2507             int cases = 0;
2508
2509             for (int i = 0; i < members.Length; i++) {
2510                 Member member = (Member)members[i];
2511                 if (member.Mapping.Xmlns != null)
2512                     continue;
2513                 if (member.Mapping.Ignore)
2514                     continue;
2515                 if (isSequence && (member.Mapping.IsText || member.Mapping.IsAttribute))
2516                     continue;
2517
2518                 bool firstElement = true;
2519                 ChoiceIdentifierAccessor choice = member.Mapping.ChoiceIdentifier;
2520                 ElementAccessor[] elements = member.Mapping.Elements;
2521
2522                 for (int j = 0; j < elements.Length; j++) {
2523                     ElementAccessor e = elements[j];
2524                     string ns = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
2525                     if (!isSequence && e.Any && (e.Name == null || e.Name.Length == 0)) continue;
2526                     if (!firstElement || (!isSequence && count > 0)) {
2527                         ilg.InitElseIf();
2528                     }
2529                     else if (isSequence) {
2530                         if (cases > 0)
2531                             ilg.InitElseIf();
2532                         else
2533                             ilg.InitIf();
2534                         ilg.Ldloc("state");
2535                         ilg.Ldc(cases);
2536                         ilg.AndIf(Cmp.EqualTo);
2537                         ilg.InitIf();
2538                     }
2539                     else {
2540                         ilg.InitIf();
2541                     }
2542                     count++;
2543                     firstElement = false;
2544                     if (member.ParamsReadSource != null) {
2545                         ILGenParamsReadSource(member.ParamsReadSource);
2546                         ilg.Ldc(false);
2547                         ilg.AndIf(Cmp.EqualTo);
2548                     }
2549                     Label labelTrue = ilg.DefineLabel();
2550                     Label labelEnd = ilg.DefineLabel();
2551                     if (member.Mapping.IsReturnValue) {
2552                         MethodInfo XmlSerializationReader_get_IsReturnValue = typeof(XmlSerializationReader).GetMethod(
2553                             "get_IsReturnValue",
2554                             CodeGenerator.InstanceBindingFlags,
2555                             null,
2556                             CodeGenerator.EmptyTypeArray,
2557                             null
2558                             );
2559                         ilg.Ldarg(0);
2560                         ilg.Call(XmlSerializationReader_get_IsReturnValue);
2561                         ilg.Brtrue(labelTrue);
2562                     }
2563                     if (isSequence && e.Any && e.AnyNamespaces == null) {
2564                         ilg.Ldc(true);
2565                     }
2566                     else {
2567                         WriteXmlNodeEqual("Reader", e.Name, ns, false);
2568                     }
2569                     if (member.Mapping.IsReturnValue) {
2570                         ilg.Br_S(labelEnd);
2571                         ilg.MarkLabel(labelTrue);
2572                         ilg.Ldc(true);
2573                         ilg.MarkLabel(labelEnd);
2574                     }
2575                     ilg.AndIf();
2576
2577                     WriteElement(member.ArraySource, member.ArrayName, member.ChoiceArraySource, e, choice, member.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite ? member.CheckSpecifiedSource : null, member.IsList && member.Mapping.TypeDesc.IsNullable, member.Mapping.ReadOnly, member.FixupIndex, j);
2578                     if (member.Mapping.IsReturnValue) {
2579                         MethodInfo XmlSerializationReader_set_IsReturnValue = typeof(XmlSerializationReader).GetMethod(
2580                             "set_IsReturnValue",
2581                             CodeGenerator.InstanceBindingFlags,
2582                             null,
2583                             new Type[] { typeof(Boolean) },
2584                             null
2585                             );
2586                         ilg.Ldarg(0);
2587                         ilg.Ldc(false);
2588                         ilg.Call(XmlSerializationReader_set_IsReturnValue);
2589                     }
2590                     if (member.ParamsReadSource != null) {
2591                         ILGenParamsReadSource(member.ParamsReadSource, true);
2592                     }
2593                 }
2594                 if (isSequence) {
2595                     if (member.IsArrayLike) {
2596                         ilg.Else();
2597                     }
2598                     else {
2599                         ilg.EndIf();
2600                     }
2601                     cases++;
2602                     ilg.Ldc(cases);
2603                     ilg.Stloc(ilg.GetLocal("state"));
2604                     if (member.IsArrayLike) {
2605                         ilg.EndIf();
2606                     }
2607                 }
2608             }
2609             if (count > 0) {
2610                 ilg.Else();
2611             }
2612             WriteMemberElementsElse(anyElement, elementElseString);
2613             if (count > 0) {
2614                 ilg.EndIf();
2615             }
2616         }
2617
2618         string GetArraySource(TypeDesc typeDesc, string arrayName) {
2619             return GetArraySource(typeDesc, arrayName, false);
2620         }
2621         string GetArraySource(TypeDesc typeDesc, string arrayName, bool multiRef) {
2622             string a = arrayName;
2623             string c = "c" + a;
2624             string init = "";
2625
2626             if (multiRef) {
2627                 init = "soap = (System.Object[])EnsureArrayIndex(soap, " + c + "+2, typeof(System.Object)); ";
2628             }
2629             if (typeDesc.IsArray) {
2630                 string arrayTypeFullName = typeDesc.ArrayElementTypeDesc.CSharpName;
2631                 string castString = "(" + arrayTypeFullName + "[])";
2632                 init = init + a + " = " + castString +
2633                     "EnsureArrayIndex(" + a + ", " + c + ", " + RaCodeGen.GetStringForTypeof(arrayTypeFullName) + ");";
2634                 string arraySource = RaCodeGen.GetStringForArrayMember(a, c + "++", typeDesc);
2635                 if (multiRef) {
2636                     init = init + " soap[1] = " + a + ";";
2637                     init = init + " if (ReadReference(out soap[" + c + "+2])) " + arraySource + " = null; else ";
2638                 }
2639                 return init + arraySource;
2640             }
2641             else {
2642                 return RaCodeGen.GetStringForMethod(arrayName, typeDesc.CSharpName, "Add");
2643
2644             }
2645         }
2646
2647
2648         void WriteMemberEnd(Member[] members) {
2649             WriteMemberEnd(members, false);
2650         }
2651
2652         void WriteMemberEnd(Member[] members, bool soapRefs) {
2653             for (int i = 0; i < members.Length; i++) {
2654                 Member member = (Member)members[i];
2655
2656                 if (member.IsArrayLike) {
2657
2658                     TypeDesc typeDesc = member.Mapping.TypeDesc;
2659
2660                     if (typeDesc.IsArray) {
2661
2662                         WriteSourceBegin(member.Source);
2663
2664                         Debug.Assert(!soapRefs);
2665
2666                         string a = member.ArrayName;
2667                         string c = "c" + a;
2668
2669                         MethodInfo XmlSerializationReader_ShrinkArray = typeof(XmlSerializationReader).GetMethod(
2670                             "ShrinkArray",
2671                             CodeGenerator.InstanceBindingFlags,
2672                             null,
2673                             new Type[] { typeof(Array), typeof(Int32), typeof(Type), typeof(Boolean) },
2674                             null
2675                             );
2676                         ilg.Ldarg(0);
2677                         ilg.Ldloc(ilg.GetLocal(a));
2678                         ilg.Ldloc(ilg.GetLocal(c));
2679                         ilg.Ldc(typeDesc.ArrayElementTypeDesc.Type);
2680                         ilg.Ldc(member.IsNullable);
2681                         ilg.Call(XmlSerializationReader_ShrinkArray);
2682                         ilg.ConvertValue(XmlSerializationReader_ShrinkArray.ReturnType, typeDesc.Type);
2683                         WriteSourceEnd(member.Source, typeDesc.Type);
2684
2685                         if (member.Mapping.ChoiceIdentifier != null) {
2686                             WriteSourceBegin(member.ChoiceSource);
2687                             a = member.ChoiceArrayName;
2688                             c = "c" + a;
2689
2690                             ilg.Ldarg(0);
2691                             ilg.Ldloc(ilg.GetLocal(a));
2692                             ilg.Ldloc(ilg.GetLocal(c));
2693                             ilg.Ldc(member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.Type);
2694                             ilg.Ldc(member.IsNullable);
2695                             ilg.Call(XmlSerializationReader_ShrinkArray);
2696                             ilg.ConvertValue(XmlSerializationReader_ShrinkArray.ReturnType, member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.Type.MakeArrayType());
2697                             WriteSourceEnd(member.ChoiceSource, member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.Type.MakeArrayType());
2698                         }
2699
2700                     }
2701                     else if (typeDesc.IsValueType) {
2702                         LocalBuilder arrayLoc = ilg.GetLocal(member.ArrayName);
2703                         WriteSourceBegin(member.Source);
2704                         ilg.Ldloc(arrayLoc);
2705                         WriteSourceEnd(member.Source, arrayLoc.LocalType);
2706                     }
2707                 }
2708             }
2709         }
2710
2711         void WriteSourceBeginTyped(string source, TypeDesc typeDesc) {
2712             WriteSourceBegin(source);
2713         }
2714
2715         void WriteSourceBegin(string source) {
2716             object variable;
2717             if (ilg.TryGetVariable(source, out variable)) {
2718                 Type varType = ilg.GetVariableType(variable);
2719                 if (CodeGenerator.IsNullableGenericType(varType)) {
2720                     // local address to invoke ctor on WriteSourceEnd
2721                     ilg.LoadAddress(variable);
2722                 }
2723                 return;
2724             }
2725             // o.@Field
2726             if (source.StartsWith("o.@", StringComparison.Ordinal)) {
2727                 ilg.LdlocAddress(ilg.GetLocal("o"));
2728                 return;
2729             }
2730             // a_0_0 = (global::System.Object[])EnsureArrayIndex(a_0_0, ca_0_0, typeof(global::System.Object));a_0_0[ca_0_0++]
2731             Regex regex = NewRegex("(?<locA1>[^ ]+) = .+EnsureArrayIndex[(](?<locA2>[^,]+), (?<locI1>[^,]+),[^;]+;(?<locA3>[^[]+)[[](?<locI2>[^+]+)[+][+][]]");
2732             Match match = regex.Match(source);
2733             if (match.Success) {
2734                 Debug.Assert(match.Groups["locA1"].Value == match.Groups["locA2"].Value);
2735                 Debug.Assert(match.Groups["locA1"].Value == match.Groups["locA3"].Value);
2736                 Debug.Assert(match.Groups["locI1"].Value == match.Groups["locI2"].Value);
2737
2738                 LocalBuilder localA = ilg.GetLocal(match.Groups["locA1"].Value);
2739                 LocalBuilder localI = ilg.GetLocal(match.Groups["locI1"].Value);
2740                 Type arrayElementType = localA.LocalType.GetElementType();
2741                 MethodInfo XmlSerializationReader_EnsureArrayIndex = typeof(XmlSerializationReader).GetMethod(
2742                     "EnsureArrayIndex",
2743                     CodeGenerator.InstanceBindingFlags,
2744                     null,
2745                     new Type[] { typeof(Array), typeof(Int32), typeof(Type) },
2746                     null
2747                     );
2748                 ilg.Ldarg(0);
2749                 ilg.Ldloc(localA);
2750                 ilg.Ldloc(localI);
2751                 ilg.Ldc(arrayElementType);
2752                 ilg.Call(XmlSerializationReader_EnsureArrayIndex);
2753                 ilg.Castclass(localA.LocalType);
2754                 ilg.Stloc(localA);
2755
2756                 // a_0[ca_0++]
2757                 ilg.Ldloc(localA);
2758                 ilg.Ldloc(localI);
2759                 ilg.Dup();
2760                 ilg.Ldc(1);
2761                 ilg.Add();
2762                 ilg.Stloc(localI);
2763                 if (CodeGenerator.IsNullableGenericType(arrayElementType) || arrayElementType.IsValueType) {
2764                     ilg.Ldelema(arrayElementType);
2765                 }
2766                 return;
2767             }
2768             //"a_0_0.Add("
2769             if (source.EndsWith(".Add(", StringComparison.Ordinal)) {
2770                 int index = source.LastIndexOf(".Add(", StringComparison.Ordinal);
2771                 LocalBuilder localA = ilg.GetLocal(source.Substring(0, index));
2772                 ilg.LdlocAddress(localA);
2773                 return;
2774             }
2775
2776             // p[0]
2777             regex = NewRegex("(?<a>[^[]+)[[](?<ia>.+)[]]");
2778             match = regex.Match(source);
2779             if (match.Success) {
2780                 System.Diagnostics.Debug.Assert(ilg.GetVariableType(ilg.GetVariable(match.Groups["a"].Value)).IsArray);
2781                 ilg.Load(ilg.GetVariable(match.Groups["a"].Value));
2782                 ilg.Load(ilg.GetVariable(match.Groups["ia"].Value));
2783                 return;
2784             }
2785             throw CodeGenerator.NotSupported("Unexpected: " + source);
2786         }
2787
2788         void WriteSourceEnd(string source, Type elementType) {
2789             WriteSourceEnd(source, elementType, elementType);
2790         }
2791         void WriteSourceEnd(string source, Type elementType, Type stackType) {
2792             object variable;
2793             if (ilg.TryGetVariable(source, out variable)) {
2794                 Type varType = ilg.GetVariableType(variable);
2795                 if (CodeGenerator.IsNullableGenericType(varType)) {
2796                     ilg.Call(varType.GetConstructor(varType.GetGenericArguments()));
2797                 }
2798                 else {
2799                     Debug.Assert(elementType != null && variable is LocalBuilder);
2800                     ilg.ConvertValue(stackType, elementType);
2801                     ilg.ConvertValue(elementType, varType);
2802                     ilg.Stloc((LocalBuilder)variable);
2803                 }
2804                 return;
2805             }
2806             // o.@Field
2807             if (source.StartsWith("o.@", StringComparison.Ordinal)) {
2808                 Debug.Assert(memberInfos.ContainsKey(source.Substring(3)));
2809                 MemberInfo memInfo = memberInfos[source.Substring(3)];
2810                 ilg.ConvertValue(stackType, memInfo.MemberType == MemberTypes.Field ? ((FieldInfo)memInfo).FieldType : ((PropertyInfo)memInfo).PropertyType);
2811                 ilg.StoreMember(memInfo);
2812                 return;
2813             }
2814             // a_0_0 = (global::System.Object[])EnsureArrayIndex(a_0_0, ca_0_0, typeof(global::System.Object));a_0_0[ca_0_0++]
2815             Regex regex = NewRegex("(?<locA1>[^ ]+) = .+EnsureArrayIndex[(](?<locA2>[^,]+), (?<locI1>[^,]+),[^;]+;(?<locA3>[^[]+)[[](?<locI2>[^+]+)[+][+][]]");
2816             Match match = regex.Match(source);
2817             if (match.Success) {
2818                 object oVar = ilg.GetVariable(match.Groups["locA1"].Value);
2819                 Type arrayElementType = ilg.GetVariableType(oVar).GetElementType();
2820                 ilg.ConvertValue(elementType, arrayElementType);
2821                 if (CodeGenerator.IsNullableGenericType(arrayElementType) || arrayElementType.IsValueType) {
2822                     ilg.Stobj(arrayElementType);
2823                 }
2824                 else {
2825                     ilg.Stelem(arrayElementType);
2826                 }
2827                 return;
2828             }
2829             //"a_0_0.Add("
2830             if (source.EndsWith(".Add(", StringComparison.Ordinal)) {
2831                 int index = source.LastIndexOf(".Add(", StringComparison.Ordinal);
2832                 LocalBuilder localA = ilg.GetLocal(source.Substring(0, index));
2833                 Debug.Assert(!localA.LocalType.IsGenericType || (localA.LocalType.GetGenericArguments().Length == 1 && localA.LocalType.GetGenericArguments()[0].IsAssignableFrom(elementType)));
2834                 MethodInfo Add = localA.LocalType.GetMethod(
2835                      "Add",
2836                      CodeGenerator.InstanceBindingFlags,
2837                      null,
2838                      new Type[] { elementType },
2839                      null
2840                      );
2841                 Debug.Assert(Add != null);
2842                 Type addParameterType = Add.GetParameters()[0].ParameterType;
2843                 ilg.ConvertValue(stackType, addParameterType);
2844                 ilg.Call(Add);
2845                 if (Add.ReturnType != typeof(void))
2846                     ilg.Pop();
2847                 return;
2848             }
2849             // p[0]
2850             regex = NewRegex("(?<a>[^[]+)[[](?<ia>.+)[]]");
2851             match = regex.Match(source);
2852             if (match.Success) {
2853                 Type varType = ilg.GetVariableType(ilg.GetVariable(match.Groups["a"].Value));
2854                 System.Diagnostics.Debug.Assert(varType.IsArray);
2855                 Type varElementType = varType.GetElementType();
2856                 ilg.ConvertValue(stackType, varElementType);
2857                 ilg.Stelem(varElementType);
2858                 return;
2859             }
2860             throw CodeGenerator.NotSupported("Unexpected: " + source);
2861         }
2862
2863         void WriteArray(string source, string arrayName, ArrayMapping arrayMapping, bool readOnly, bool isNullable, int fixupIndex, int elementIndex) {
2864             MethodInfo XmlSerializationReader_ReadNull = typeof(XmlSerializationReader).GetMethod(
2865                 "ReadNull",
2866                 CodeGenerator.InstanceBindingFlags,
2867                 null,
2868                 CodeGenerator.EmptyTypeArray,
2869                 null
2870                 );
2871             ilg.Ldarg(0);
2872             ilg.Call(XmlSerializationReader_ReadNull);
2873             ilg.IfNot();
2874
2875             MemberMapping memberMapping = new MemberMapping();
2876             memberMapping.Elements = arrayMapping.Elements;
2877             memberMapping.TypeDesc = arrayMapping.TypeDesc;
2878             memberMapping.ReadOnly = readOnly;
2879             if (source.StartsWith("o.@", StringComparison.Ordinal)) {
2880                 Debug.Assert(memberInfos.ContainsKey(source.Substring(3)));
2881                 memberMapping.MemberInfo = memberInfos[source.Substring(3)];
2882             }
2883             Member member = new Member(this, source, arrayName, elementIndex, memberMapping, false);
2884             member.IsNullable = false;//Note, [....]: IsNullable is set to false since null condition (xsi:nil) is already handled by 'ReadNull()'
2885
2886             Member[] members = new Member[] { member };
2887             WriteMemberBegin(members);
2888             Label labelTrue = ilg.DefineLabel();
2889             Label labelEnd = ilg.DefineLabel();
2890
2891             if (readOnly) {
2892                 ilg.Load(ilg.GetVariable(member.ArrayName));
2893                 ilg.Load(null);
2894                 ilg.Beq(labelTrue);
2895             }
2896             else {
2897             }
2898             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
2899                 "get_Reader",
2900                 CodeGenerator.InstanceBindingFlags,
2901                 null,
2902                 CodeGenerator.EmptyTypeArray,
2903                 null
2904                 );
2905             MethodInfo XmlReader_get_IsEmptyElement = typeof(XmlReader).GetMethod(
2906                 "get_IsEmptyElement",
2907                 CodeGenerator.InstanceBindingFlags,
2908                 null,
2909                 CodeGenerator.EmptyTypeArray,
2910                 null
2911                 );
2912             ilg.Ldarg(0);
2913             ilg.Call(XmlSerializationReader_get_Reader);
2914             ilg.Call(XmlReader_get_IsEmptyElement);
2915             if (readOnly) {
2916                 ilg.Br_S(labelEnd);
2917                 ilg.MarkLabel(labelTrue);
2918                 ilg.Ldc(true);
2919                 ilg.MarkLabel(labelEnd);
2920             }
2921             ilg.If();
2922             MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
2923                 "Skip",
2924                 CodeGenerator.InstanceBindingFlags,
2925                 null,
2926                 CodeGenerator.EmptyTypeArray,
2927                 null
2928                 );
2929             ilg.Ldarg(0);
2930             ilg.Call(XmlSerializationReader_get_Reader);
2931             ilg.Call(XmlReader_Skip);
2932             ilg.Else();
2933
2934             MethodInfo XmlReader_ReadStartElement = typeof(XmlReader).GetMethod(
2935                 "ReadStartElement",
2936                 CodeGenerator.InstanceBindingFlags,
2937                 null,
2938                 CodeGenerator.EmptyTypeArray,
2939                 null
2940                 );
2941             ilg.Ldarg(0);
2942             ilg.Call(XmlSerializationReader_get_Reader);
2943             ilg.Call(XmlReader_ReadStartElement);
2944             int loopIndex = WriteWhileNotLoopStart();
2945
2946             string unknownNode = "UnknownNode(null, " + ExpectedElements(members) + ");";
2947             WriteMemberElements(members, unknownNode, unknownNode, null, null);
2948             MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
2949                 "MoveToContent",
2950                 CodeGenerator.InstanceBindingFlags,
2951                 null,
2952                 CodeGenerator.EmptyTypeArray,
2953                 null
2954                 );
2955             ilg.Ldarg(0);
2956             ilg.Call(XmlSerializationReader_get_Reader);
2957             ilg.Call(XmlReader_MoveToContent);
2958             ilg.Pop();
2959
2960             WriteWhileLoopEnd(loopIndex);
2961             MethodInfo XmlSerializationReader_ReadEndElement = typeof(XmlSerializationReader).GetMethod(
2962                 "ReadEndElement",
2963                 CodeGenerator.InstanceBindingFlags,
2964                 null,
2965                 CodeGenerator.EmptyTypeArray,
2966                 null
2967                 );
2968             ilg.Ldarg(0);
2969             ilg.Call(XmlSerializationReader_ReadEndElement);
2970             ilg.EndIf();
2971
2972             WriteMemberEnd(members, false);
2973
2974             if (isNullable) {
2975                 ilg.Else();
2976                 member.IsNullable = true;
2977                 WriteMemberBegin(members);
2978                 WriteMemberEnd(members);
2979             }
2980             ilg.EndIf();
2981         }
2982
2983         void WriteElement(string source, string arrayName, string choiceSource, ElementAccessor element, ChoiceIdentifierAccessor choice, string checkSpecified, bool checkForNull, bool readOnly, int fixupIndex, int elementIndex) {
2984             if (checkSpecified != null && checkSpecified.Length > 0) {
2985                 ILGenSet(checkSpecified, true);
2986             }
2987
2988             if (element.Mapping is ArrayMapping) {
2989                 WriteArray(source, arrayName, (ArrayMapping)element.Mapping, readOnly, element.IsNullable, fixupIndex, elementIndex);
2990             }
2991             else if (element.Mapping is NullableMapping) {
2992                 string methodName = ReferenceMapping(element.Mapping);
2993 #if DEBUG
2994                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
2995                 if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, element.Mapping.TypeDesc.Name));
2996 #endif
2997                 WriteSourceBegin(source);
2998                 ilg.Ldarg(0);
2999                 ilg.Ldc(true);
3000                 MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
3001                     methodName,
3002                     CodeGenerator.PrivateMethodAttributes,
3003                     // See WriteNullableMethod for different return type logic
3004                     element.Mapping.TypeDesc.Type,
3005                     new Type[] { typeof(Boolean) }
3006                     );
3007                 ilg.Call(methodBuilder);
3008                 WriteSourceEnd(source, element.Mapping.TypeDesc.Type);
3009             }
3010             else if (element.Mapping is PrimitiveMapping) {
3011                 bool doEndIf = false;
3012                 if (element.IsNullable) {
3013                     MethodInfo XmlSerializationReader_ReadNull = typeof(XmlSerializationReader).GetMethod(
3014                          "ReadNull",
3015                          CodeGenerator.InstanceBindingFlags,
3016                          null,
3017                          CodeGenerator.EmptyTypeArray,
3018                          null
3019                          );
3020                     ilg.Ldarg(0);
3021                     ilg.Call(XmlSerializationReader_ReadNull);
3022                     ilg.If();
3023                     WriteSourceBegin(source);
3024                     if (element.Mapping.TypeDesc.IsValueType) {
3025                         throw CodeGenerator.NotSupported("No such condition.  PrimitiveMapping && IsNullable = String, XmlQualifiedName and never IsValueType");
3026                     }
3027                     else {
3028                         ilg.Load(null);
3029                     }
3030                     WriteSourceEnd(source, element.Mapping.TypeDesc.Type);
3031                     ilg.Else();
3032                     doEndIf = true;
3033                 }
3034                 if (element.Default != null && element.Default != DBNull.Value && element.Mapping.TypeDesc.IsValueType) {
3035                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
3036                         "get_Reader",
3037                         CodeGenerator.InstanceBindingFlags,
3038                         null,
3039                         CodeGenerator.EmptyTypeArray,
3040                         null
3041                         );
3042                     MethodInfo XmlReader_get_IsEmptyElement = typeof(XmlReader).GetMethod(
3043                         "get_IsEmptyElement",
3044                         CodeGenerator.InstanceBindingFlags,
3045                         null,
3046                         CodeGenerator.EmptyTypeArray,
3047                         null
3048                         );
3049                     ilg.Ldarg(0);
3050                     ilg.Call(XmlSerializationReader_get_Reader);
3051                     ilg.Call(XmlReader_get_IsEmptyElement);
3052                     ilg.If();
3053                     MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
3054                         "Skip",
3055                         CodeGenerator.InstanceBindingFlags,
3056                         null,
3057                         CodeGenerator.EmptyTypeArray,
3058                         null
3059                         );
3060                     ilg.Ldarg(0);
3061                     ilg.Call(XmlSerializationReader_get_Reader);
3062                     ilg.Call(XmlReader_Skip);
3063                     ilg.Else();
3064                     doEndIf = true;
3065                 }
3066                 else {
3067                 }
3068
3069                 WriteSourceBegin(source);
3070                 if (element.Mapping.TypeDesc == QnameTypeDesc) {
3071                     MethodInfo XmlSerializationReader_ReadElementQualifiedName = typeof(XmlSerializationReader).GetMethod(
3072                            "ReadElementQualifiedName",
3073                            CodeGenerator.InstanceBindingFlags,
3074                            null,
3075                            CodeGenerator.EmptyTypeArray,
3076                            null
3077                            );
3078                     ilg.Ldarg(0);
3079                     ilg.Call(XmlSerializationReader_ReadElementQualifiedName);
3080                 }
3081                 else {
3082                     string readFunc;
3083                     switch (element.Mapping.TypeDesc.FormatterName) {
3084                         case "ByteArrayBase64":
3085                         case "ByteArrayHex":
3086                             readFunc = "false";
3087                             break;
3088                         default:
3089                             readFunc = "Reader.ReadElementString()";
3090                             break;
3091                     }
3092                     WritePrimitive(element.Mapping, readFunc);
3093                 }
3094
3095                 WriteSourceEnd(source, element.Mapping.TypeDesc.Type);
3096                 if (doEndIf)
3097                     ilg.EndIf();
3098             }
3099             else if (element.Mapping is StructMapping) {
3100                 TypeMapping mapping = element.Mapping;
3101                 string methodName = ReferenceMapping(mapping);
3102 #if DEBUG
3103                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
3104                 if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name));
3105 #endif
3106
3107                 if (checkForNull) {
3108                     MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
3109                         "get_Reader",
3110                         CodeGenerator.InstanceBindingFlags,
3111                         null,
3112                         CodeGenerator.EmptyTypeArray,
3113                         null
3114                         );
3115                     MethodInfo XmlReader_Skip = typeof(XmlReader).GetMethod(
3116                         "Skip",
3117                         CodeGenerator.InstanceBindingFlags,
3118                         null,
3119                         CodeGenerator.EmptyTypeArray,
3120                         null
3121                         );
3122                     ilg.Ldloc(arrayName);
3123                     ilg.Load(null);
3124                     ilg.If(Cmp.EqualTo);
3125                     ilg.Ldarg(0);
3126                     ilg.Call(XmlSerializationReader_get_Reader);
3127                     ilg.Call(XmlReader_Skip);
3128                     ilg.Else();
3129                 }
3130                 WriteSourceBegin(source);
3131                 List<Type> argTypes = new List<Type>();
3132                 ilg.Ldarg(0);
3133                 if (mapping.TypeDesc.IsNullable) {
3134                     ilg.Load(element.IsNullable);
3135                     argTypes.Add(typeof(Boolean));
3136                 }
3137                 ilg.Ldc(true);
3138                 argTypes.Add(typeof(Boolean));
3139                 MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
3140                     methodName,
3141                     CodeGenerator.PrivateMethodAttributes,
3142                     mapping.TypeDesc.Type,
3143                     argTypes.ToArray()
3144                     );
3145                 ilg.Call(methodBuilder);
3146                 WriteSourceEnd(source, mapping.TypeDesc.Type);
3147                 if (checkForNull)
3148                     // 'If' begins in checkForNull above
3149                     ilg.EndIf();
3150             }
3151             else if (element.Mapping is SpecialMapping) {
3152                 SpecialMapping special = (SpecialMapping)element.Mapping;
3153                 switch (special.TypeDesc.Kind) {
3154                     case TypeKind.Node:
3155                         bool isDoc = special.TypeDesc.FullName == typeof(XmlDocument).FullName;
3156                         WriteSourceBeginTyped(source, special.TypeDesc);
3157                         MethodInfo XmlSerializationReader_ReadXmlXXX = typeof(XmlSerializationReader).GetMethod(
3158                               isDoc ? "ReadXmlDocument" : "ReadXmlNode",
3159                               CodeGenerator.InstanceBindingFlags,
3160                               null,
3161                               new Type[] { typeof(Boolean) },
3162                               null
3163                               );
3164                         ilg.Ldarg(0);
3165                         ilg.Ldc(element.Any ? false : true);
3166                         ilg.Call(XmlSerializationReader_ReadXmlXXX);
3167                         // See logic in WriteSourceBeginTyped whether or not to castclass.
3168                         if (special.TypeDesc != null)
3169                             ilg.Castclass(special.TypeDesc.Type);
3170                         WriteSourceEnd(source, special.TypeDesc.Type);
3171                         break;
3172                     case TypeKind.Serializable:
3173                         SerializableMapping sm = (SerializableMapping)element.Mapping;
3174                         // check to see if we need to do the derivation
3175                         if (sm.DerivedMappings != null) {
3176                             MethodInfo XmlSerializationReader_GetXsiType = typeof(XmlSerializationReader).GetMethod(
3177                                 "GetXsiType",
3178                                 CodeGenerator.InstanceBindingFlags,
3179                                 null,
3180                                 CodeGenerator.EmptyTypeArray,
3181                                 null
3182                                 );
3183                             Label labelTrue = ilg.DefineLabel();
3184                             Label labelEnd = ilg.DefineLabel();
3185                             LocalBuilder tserLoc = ilg.DeclareOrGetLocal(typeof(XmlQualifiedName), "tser");
3186                             ilg.Ldarg(0);
3187                             ilg.Call(XmlSerializationReader_GetXsiType);
3188                             ilg.Stloc(tserLoc);
3189                             ilg.Ldloc(tserLoc);
3190                             ilg.Load(null);
3191                             ilg.Ceq();
3192                             ilg.Brtrue(labelTrue);
3193                             WriteQNameEqual("tser", sm.XsiType.Name, sm.XsiType.Namespace);
3194
3195                             ilg.Br_S(labelEnd);
3196                             ilg.MarkLabel(labelTrue);
3197                             ilg.Ldc(true);
3198                             ilg.MarkLabel(labelEnd);
3199                             ilg.If();
3200                         }
3201                         WriteSourceBeginTyped(source, sm.TypeDesc);
3202                         bool isWrappedAny = !element.Any && IsWildcard(sm);
3203                         MethodInfo XmlSerializationReader_ReadSerializable = typeof(XmlSerializationReader).GetMethod(
3204                              "ReadSerializable",
3205                              CodeGenerator.InstanceBindingFlags,
3206                              null,
3207                              isWrappedAny ? new Type[] { typeof(IXmlSerializable), typeof(Boolean) } : new Type[] { typeof(IXmlSerializable) },
3208                              null
3209                              );
3210                         ilg.Ldarg(0);
3211                         RaCodeGen.ILGenForCreateInstance(ilg, sm.TypeDesc.Type, sm.TypeDesc.CannotNew, false);
3212                         if (sm.TypeDesc.CannotNew)
3213                             ilg.ConvertValue(typeof(object), typeof(IXmlSerializable));
3214                         if (isWrappedAny)
3215                             ilg.Ldc(true);
3216                         ilg.Call(XmlSerializationReader_ReadSerializable);
3217                         // See logic in WriteSourceBeginTyped whether or not to castclass.
3218                         if (sm.TypeDesc != null)
3219                             ilg.ConvertValue(typeof(IXmlSerializable), sm.TypeDesc.Type);
3220                         WriteSourceEnd(source, sm.TypeDesc.Type);
3221                         if (sm.DerivedMappings != null) {
3222                             WriteDerivedSerializable(sm, sm, source, isWrappedAny);
3223                             WriteUnknownNode("UnknownNode", "null", null, true);
3224                         }
3225                         break;
3226                     default:
3227                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
3228                 }
3229             }
3230             else {
3231                 throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
3232             }
3233             if (choice != null) {
3234 #if DEBUG
3235                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
3236                 if (choiceSource == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "need parent for the " + source));
3237 #endif
3238
3239                 WriteSourceBegin(choiceSource);
3240                 CodeIdentifier.CheckValidIdentifier(choice.MemberIds[elementIndex]);
3241                 RaCodeGen.ILGenForEnumMember(ilg, choice.Mapping.TypeDesc.Type, choice.MemberIds[elementIndex]);
3242                 WriteSourceEnd(choiceSource, choice.Mapping.TypeDesc.Type);
3243             }
3244         }
3245
3246         void WriteDerivedSerializable(SerializableMapping head, SerializableMapping mapping, string source, bool isWrappedAny) {
3247             if (mapping == null)
3248                 return;
3249             for (SerializableMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
3250                 Label labelTrue = ilg.DefineLabel();
3251                 Label labelEnd = ilg.DefineLabel();
3252                 LocalBuilder tserLoc = ilg.GetLocal("tser");
3253                 ilg.InitElseIf();
3254                 ilg.Ldloc(tserLoc);
3255                 ilg.Load(null);
3256                 ilg.Ceq();
3257                 ilg.Brtrue(labelTrue);
3258                 WriteQNameEqual("tser", derived.XsiType.Name, derived.XsiType.Namespace);
3259
3260                 ilg.Br_S(labelEnd);
3261                 ilg.MarkLabel(labelTrue);
3262                 ilg.Ldc(true);
3263                 ilg.MarkLabel(labelEnd);
3264                 ilg.AndIf();
3265
3266                 if (derived.Type != null) {
3267                     if (head.Type.IsAssignableFrom(derived.Type)) {
3268                         WriteSourceBeginTyped(source, head.TypeDesc);
3269                         MethodInfo XmlSerializationReader_ReadSerializable = typeof(XmlSerializationReader).GetMethod(
3270                              "ReadSerializable",
3271                              CodeGenerator.InstanceBindingFlags,
3272                              null,
3273                              isWrappedAny ? new Type[] { typeof(IXmlSerializable), typeof(Boolean) } : new Type[] { typeof(IXmlSerializable) },
3274                              null
3275                              );
3276                         ilg.Ldarg(0);
3277                         RaCodeGen.ILGenForCreateInstance(ilg, derived.TypeDesc.Type, derived.TypeDesc.CannotNew, false);
3278                         if (derived.TypeDesc.CannotNew)
3279                             ilg.ConvertValue(typeof(object), typeof(IXmlSerializable));
3280                         if (isWrappedAny)
3281                             ilg.Ldc(true);
3282                         ilg.Call(XmlSerializationReader_ReadSerializable);
3283                         // See logic in WriteSourceBeginTyped whether or not to castclass.
3284                         if (head.TypeDesc != null)
3285                             ilg.ConvertValue(typeof(IXmlSerializable), head.TypeDesc.Type);
3286                         WriteSourceEnd(source, head.TypeDesc.Type);
3287                     }
3288                     else {
3289                         MethodInfo XmlSerializationReader_CreateBadDerivationException = typeof(XmlSerializationReader).GetMethod(
3290                            "CreateBadDerivationException",
3291                            CodeGenerator.InstanceBindingFlags,
3292                            null,
3293                            new Type[] { typeof(String), typeof(String), typeof(String), typeof(String), typeof(String), typeof(String) },
3294                            null
3295                            );
3296                         ilg.Ldarg(0);
3297                         ilg.Ldstr(derived.XsiType.Name);
3298                         ilg.Ldstr(derived.XsiType.Namespace);
3299                         ilg.Ldstr(head.XsiType.Name);
3300                         ilg.Ldstr(head.XsiType.Namespace);
3301                         ilg.Ldstr(derived.Type.FullName);
3302                         ilg.Ldstr(head.Type.FullName);
3303                         ilg.Call(XmlSerializationReader_CreateBadDerivationException);
3304                         ilg.Throw();
3305                     }
3306                 }
3307                 else {
3308                     MethodInfo XmlSerializationReader_CreateMissingIXmlSerializableType = typeof(XmlSerializationReader).GetMethod(
3309                        "CreateMissingIXmlSerializableType",
3310                        CodeGenerator.InstanceBindingFlags,
3311                        null,
3312                        new Type[] { typeof(String), typeof(String), typeof(String) },
3313                        null
3314                        );
3315                     ilg.Ldarg(0);
3316                     ilg.Ldstr(derived.XsiType.Name);
3317                     ilg.Ldstr(derived.XsiType.Namespace);
3318                     ilg.Ldstr(head.Type.FullName);
3319                     ilg.Call(XmlSerializationReader_CreateMissingIXmlSerializableType);
3320                     ilg.Throw();
3321                 }
3322
3323
3324                 WriteDerivedSerializable(head, derived, source, isWrappedAny);
3325             }
3326         }
3327
3328         int WriteWhileNotLoopStart() {
3329             MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
3330                 "get_Reader",
3331                 CodeGenerator.InstanceBindingFlags,
3332                 null,
3333                 CodeGenerator.EmptyTypeArray,
3334                 null
3335                 );
3336             MethodInfo XmlReader_MoveToContent = typeof(XmlReader).GetMethod(
3337                 "MoveToContent",
3338                 CodeGenerator.InstanceBindingFlags,
3339                 null,
3340                 CodeGenerator.EmptyTypeArray,
3341                 null
3342                 );
3343             ilg.Ldarg(0);
3344             ilg.Call(XmlSerializationReader_get_Reader);
3345             ilg.Call(XmlReader_MoveToContent);
3346             ilg.Pop();
3347             int loopIndex = WriteWhileLoopStartCheck();
3348             ilg.WhileBegin();
3349             return loopIndex;
3350         }
3351
3352         void WriteWhileLoopEnd(int loopIndex) {
3353             WriteWhileLoopEndCheck(loopIndex);
3354             ilg.WhileBeginCondition();
3355             {
3356                 int XmlNodeType_None = 0;
3357                 //int XmlNodeType_Element = 1;
3358                 int XmlNodeType_EndElement = 15;
3359
3360                 MethodInfo XmlSerializationReader_get_Reader = typeof(XmlSerializationReader).GetMethod(
3361                     "get_Reader",
3362                     CodeGenerator.InstanceBindingFlags,
3363                     null,
3364                     CodeGenerator.EmptyTypeArray,
3365                     null
3366                     );
3367                 MethodInfo XmlReader_get_NodeType = typeof(XmlReader).GetMethod(
3368                     "get_NodeType",
3369                     CodeGenerator.InstanceBindingFlags,
3370                     null,
3371                     CodeGenerator.EmptyTypeArray,
3372                     null
3373                     );
3374                 Label labelFalse = ilg.DefineLabel();
3375                 Label labelEnd = ilg.DefineLabel();
3376                 ilg.Ldarg(0);
3377                 ilg.Call(XmlSerializationReader_get_Reader);
3378                 ilg.Call(XmlReader_get_NodeType);
3379                 ilg.Ldc(XmlNodeType_EndElement);
3380                 ilg.Beq(labelFalse);
3381                 ilg.Ldarg(0);
3382                 ilg.Call(XmlSerializationReader_get_Reader);
3383                 ilg.Call(XmlReader_get_NodeType);
3384                 ilg.Ldc(XmlNodeType_None);
3385                 ilg.Cne();
3386                 ilg.Br_S(labelEnd);
3387                 ilg.MarkLabel(labelFalse);
3388                 ilg.Ldc(false);
3389                 ilg.MarkLabel(labelEnd);
3390             }
3391             ilg.WhileEndCondition();
3392             ilg.WhileEnd();
3393         }
3394
3395         int WriteWhileLoopStartCheck() {
3396             MethodInfo XmlSerializationReader_get_ReaderCount = typeof(XmlSerializationReader).GetMethod(
3397                 "get_ReaderCount",
3398                 CodeGenerator.InstanceBindingFlags,
3399                 null,
3400                 CodeGenerator.EmptyTypeArray,
3401                 null
3402                 );
3403             ilg.Ldc(0);
3404             ilg.Stloc(typeof(Int32), String.Format(CultureInfo.InvariantCulture, "whileIterations{0}", nextWhileLoopIndex));
3405             ilg.Ldarg(0);
3406             ilg.Call(XmlSerializationReader_get_ReaderCount);
3407             ilg.Stloc(typeof(Int32), String.Format(CultureInfo.InvariantCulture, "readerCount{0}", nextWhileLoopIndex));
3408             return nextWhileLoopIndex++;
3409         }
3410
3411         void WriteWhileLoopEndCheck(int loopIndex) {
3412             Type refIntType = Type.GetType("System.Int32&");
3413             MethodInfo XmlSerializationReader_CheckReaderCount = typeof(XmlSerializationReader).GetMethod(
3414                "CheckReaderCount",
3415                CodeGenerator.InstanceBindingFlags,
3416                null,
3417                new Type[] { refIntType, refIntType },
3418                null
3419                );
3420             ilg.Ldarg(0);
3421             ilg.Ldloca(ilg.GetLocal(String.Format(CultureInfo.InvariantCulture, "whileIterations{0}", loopIndex)));
3422             ilg.Ldloca(ilg.GetLocal(String.Format(CultureInfo.InvariantCulture, "readerCount{0}", loopIndex)));
3423             ilg.Call(XmlSerializationReader_CheckReaderCount);
3424         }
3425
3426         void WriteParamsRead(int length) {
3427             LocalBuilder paramsRead = ilg.DeclareLocal(typeof(Boolean[]), "paramsRead");
3428             ilg.NewArray(typeof(Boolean), length);
3429             ilg.Stloc(paramsRead);
3430         }
3431
3432         void WriteCreateMapping(TypeMapping mapping, string local) {
3433             string fullTypeName = mapping.TypeDesc.CSharpName;
3434             bool ctorInaccessible = mapping.TypeDesc.CannotNew;
3435
3436             LocalBuilder loc = ilg.DeclareLocal(
3437                 mapping.TypeDesc.Type,
3438                 local);
3439
3440             if (ctorInaccessible) {
3441                 ilg.BeginExceptionBlock();
3442             }
3443             RaCodeGen.ILGenForCreateInstance(ilg, mapping.TypeDesc.Type, mapping.TypeDesc.CannotNew, true);
3444             ilg.Stloc(loc);
3445             if (ctorInaccessible) {
3446                 ilg.Leave();
3447                 WriteCatchException(typeof(MissingMethodException));
3448                 MethodInfo XmlSerializationReader_CreateInaccessibleConstructorException = typeof(XmlSerializationReader).GetMethod(
3449                       "CreateInaccessibleConstructorException",
3450                       CodeGenerator.InstanceBindingFlags,
3451                       null,
3452                       new Type[] { typeof(String) },
3453                       null
3454                       );
3455                 ilg.Ldarg(0);
3456                 ilg.Ldstr(fullTypeName);
3457                 ilg.Call(XmlSerializationReader_CreateInaccessibleConstructorException);
3458                 ilg.Throw();
3459
3460                 WriteCatchException(typeof(SecurityException));
3461                 MethodInfo XmlSerializationReader_CreateCtorHasSecurityException = typeof(XmlSerializationReader).GetMethod(
3462                     "CreateCtorHasSecurityException",
3463                     CodeGenerator.InstanceBindingFlags,
3464                     null,
3465                     new Type[] { typeof(String) },
3466                     null
3467                     );
3468                 ilg.Ldarg(0);
3469                 ilg.Ldstr(fullTypeName);
3470                 ilg.Call(XmlSerializationReader_CreateCtorHasSecurityException);
3471                 ilg.Throw();
3472
3473                 ilg.EndExceptionBlock();
3474             }
3475         }
3476
3477         void WriteCatchException(Type exceptionType) {
3478             ilg.BeginCatchBlock(exceptionType);
3479             ilg.Pop();
3480         }
3481
3482         void WriteCatchCastException(TypeDesc typeDesc, string source, string id) {
3483             WriteCatchException(typeof(InvalidCastException));
3484             MethodInfo XmlSerializationReader_CreateInvalidCastException = typeof(XmlSerializationReader).GetMethod(
3485                 "CreateInvalidCastException",
3486                 CodeGenerator.InstanceBindingFlags,
3487                 null,
3488                 new Type[] { typeof(Type), typeof(Object), typeof(String) },
3489                 null
3490                 );
3491             ilg.Ldarg(0);
3492             ilg.Ldc(typeDesc.Type);
3493
3494             // GetTarget(ids[0])
3495             if (source.StartsWith("GetTarget(ids[", StringComparison.Ordinal)) {
3496                 MethodInfo XmlSerializationReader_GetTarget = typeof(XmlSerializationReader).GetMethod(
3497                     "GetTarget",
3498                     CodeGenerator.InstanceBindingFlags,
3499                     null,
3500                     new Type[] { typeof(String) },
3501                     null
3502                     );
3503                 object idsLoc = ilg.GetVariable("ids");
3504                 ilg.Ldarg(0);
3505                 // Parse index
3506                 ilg.LoadArrayElement(idsLoc, Int32.Parse(source.Substring(14, source.Length - 16), CultureInfo.InvariantCulture));
3507                 ilg.Call(XmlSerializationReader_GetTarget);
3508             }
3509             else {
3510                 ilg.Load(ilg.GetVariable(source));
3511             }
3512
3513             if (id == null)
3514                 ilg.Load(null);
3515             else {
3516                 // ids[0]
3517                 if (id.StartsWith("ids[", StringComparison.Ordinal)) {
3518                     object idsLoc = ilg.GetVariable("ids");
3519                     // Parse index
3520                     ilg.LoadArrayElement(idsLoc, Int32.Parse(id.Substring(4, id.Length - 5), CultureInfo.InvariantCulture));
3521                 }
3522                 else {
3523                     object idVar = ilg.GetVariable(id);
3524                     ilg.Load(idVar);
3525                     ilg.ConvertValue(ilg.GetVariableType(idVar), typeof(string));
3526                 }
3527             }
3528             ilg.Call(XmlSerializationReader_CreateInvalidCastException);
3529             ilg.Throw();
3530         }
3531         void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
3532             RaCodeGen.WriteArrayLocalDecl(typeName, variableName, new SourceInfo(initValue, initValue, null, arrayTypeDesc.Type, ilg), arrayTypeDesc);
3533         }
3534         void WriteCreateInstance(string source, bool ctorInaccessible, Type type) {
3535             RaCodeGen.WriteCreateInstance(source, ctorInaccessible, type, ilg);
3536         }
3537         void WriteLocalDecl(string variableName, SourceInfo initValue) {
3538             RaCodeGen.WriteLocalDecl(variableName, initValue);
3539         }
3540         void ILGenElseString(string elseString) {
3541             MethodInfo XmlSerializationReader_UnknownNode1 = typeof(XmlSerializationReader).GetMethod(
3542                   "UnknownNode",
3543                   CodeGenerator.InstanceBindingFlags,
3544                   null,
3545                   new Type[] { typeof(object) },
3546                   null
3547                   );
3548             MethodInfo XmlSerializationReader_UnknownNode2 = typeof(XmlSerializationReader).GetMethod(
3549                   "UnknownNode",
3550                   CodeGenerator.InstanceBindingFlags,
3551                   null,
3552                   new Type[] { typeof(object), typeof(string) },
3553                   null
3554                   );
3555             // UnknownNode(null, @":anyType");
3556             Regex regex = NewRegex("UnknownNode[(]null, @[\"](?<qnames>[^\"]*)[\"][)];");
3557             Match match = regex.Match(elseString);
3558             if (match.Success) {
3559                 ilg.Ldarg(0);
3560                 ilg.Load(null);
3561                 ilg.Ldstr(match.Groups["qnames"].Value);
3562                 ilg.Call(XmlSerializationReader_UnknownNode2);
3563                 return;
3564             }
3565             // UnknownNode((object)o, @"");
3566             regex = NewRegex("UnknownNode[(][(]object[)](?<o>[^,]+), @[\"](?<qnames>[^\"]*)[\"][)];");
3567             match = regex.Match(elseString);
3568             if (match.Success) {
3569                 ilg.Ldarg(0);
3570                 LocalBuilder localO = ilg.GetLocal(match.Groups["o"].Value);
3571                 ilg.Ldloc(localO);
3572                 ilg.ConvertValue(localO.LocalType, typeof(object));
3573                 ilg.Ldstr(match.Groups["qnames"].Value);
3574                 ilg.Call(XmlSerializationReader_UnknownNode2);
3575                 return;
3576             }
3577             // UnknownNode((object)o, null);
3578             regex = NewRegex("UnknownNode[(][(]object[)](?<o>[^,]+), null[)];");
3579             match = regex.Match(elseString);
3580             if (match.Success) {
3581                 ilg.Ldarg(0);
3582                 LocalBuilder localO = ilg.GetLocal(match.Groups["o"].Value);
3583                 ilg.Ldloc(localO);
3584                 ilg.ConvertValue(localO.LocalType, typeof(object));
3585                 ilg.Load(null);
3586                 ilg.Call(XmlSerializationReader_UnknownNode2);
3587                 return;
3588             }
3589             // "UnknownNode((object)o);"
3590             regex = NewRegex("UnknownNode[(][(]object[)](?<o>[^)]+)[)];");
3591             match = regex.Match(elseString);
3592             if (match.Success) {
3593                 ilg.Ldarg(0);
3594                 LocalBuilder localO = ilg.GetLocal(match.Groups["o"].Value);
3595                 ilg.Ldloc(localO);
3596                 ilg.ConvertValue(localO.LocalType, typeof(object));
3597                 ilg.Call(XmlSerializationReader_UnknownNode1);
3598                 return;
3599             }
3600             throw CodeGenerator.NotSupported("Unexpected: " + elseString);
3601         }
3602         void ILGenParamsReadSource(string paramsReadSource) {
3603             Regex regex = NewRegex("paramsRead\\[(?<index>[0-9]+)\\]");
3604             Match match = regex.Match(paramsReadSource);
3605             if (match.Success) {
3606                 ilg.LoadArrayElement(ilg.GetLocal("paramsRead"), Int32.Parse(match.Groups["index"].Value, CultureInfo.InvariantCulture));
3607                 return;
3608             }
3609             throw CodeGenerator.NotSupported("Unexpected: " + paramsReadSource);
3610         }
3611         void ILGenParamsReadSource(string paramsReadSource, bool value) {
3612             Regex regex = NewRegex("paramsRead\\[(?<index>[0-9]+)\\]");
3613             Match match = regex.Match(paramsReadSource);
3614             if (match.Success) {
3615                 ilg.StoreArrayElement(ilg.GetLocal("paramsRead"), Int32.Parse(match.Groups["index"].Value, CultureInfo.InvariantCulture), value);
3616                 return;
3617             }
3618             throw CodeGenerator.NotSupported("Unexpected: " + paramsReadSource);
3619         }
3620         void ILGenElementElseString(string elementElseString) {
3621             if (elementElseString == "throw CreateUnknownNodeException();") {
3622                 MethodInfo XmlSerializationReader_CreateUnknownNodeException = typeof(XmlSerializationReader).GetMethod(
3623                        "CreateUnknownNodeException",
3624                        CodeGenerator.InstanceBindingFlags,
3625                        null,
3626                        CodeGenerator.EmptyTypeArray,
3627                        null
3628                        );
3629                 ilg.Ldarg(0);
3630                 ilg.Call(XmlSerializationReader_CreateUnknownNodeException);
3631                 ilg.Throw();
3632                 return;
3633             }
3634             if (elementElseString.StartsWith("UnknownNode(", StringComparison.Ordinal)) {
3635                 ILGenElseString(elementElseString);
3636                 return;
3637             }
3638             throw CodeGenerator.NotSupported("Unexpected: " + elementElseString);
3639         }
3640         void ILGenSet(string source, object value) {
3641             WriteSourceBegin(source);
3642             ilg.Load(value);
3643             WriteSourceEnd(source, value == null ? typeof(object) : value.GetType());
3644         }
3645     }
3646 }