5a3d21642d46f4e2e06e88f9fc591742bf823d14
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Serialization / XmlSerializationReader.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSerializationReader.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>                                                                
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Serialization {
9
10     using System.IO;
11     using System;
12     using System.Security;
13     using System.Collections;
14     using System.Reflection;
15     using System.Text;
16     using System.Xml;
17     using System.Xml.Schema;
18     using System.ComponentModel;
19     using System.Globalization;
20     using System.CodeDom.Compiler;
21     using System.Diagnostics;
22     using System.Threading;
23     using System.Configuration;
24     using System.Xml.Serialization.Configuration;
25
26     /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader"]/*' />
27     ///<internalonly/>
28     public abstract class XmlSerializationReader : XmlSerializationGeneratedCode {
29         XmlReader r;
30         XmlCountingReader countingReader;
31         XmlDocument d;
32         Hashtable callbacks;
33         Hashtable types;
34         Hashtable typesReverse;
35         XmlDeserializationEvents events;
36         Hashtable targets;
37         Hashtable referencedTargets;
38         ArrayList targetsWithoutIds;
39         ArrayList fixups;
40         ArrayList collectionFixups;
41         bool soap12;
42         bool isReturnValue;
43         bool decodeName = true;
44
45         string schemaNsID;
46         string schemaNs1999ID;
47         string schemaNs2000ID;
48         string schemaNonXsdTypesNsID;
49         string instanceNsID;
50         string instanceNs2000ID;
51         string instanceNs1999ID;
52         string soapNsID;
53         string soap12NsID;
54         string schemaID;
55         string wsdlNsID;
56         string wsdlArrayTypeID;
57         string nullID;
58         string nilID;
59         string typeID;
60         string arrayTypeID;
61         string itemTypeID;
62         string arraySizeID;
63         string arrayID;
64         string urTypeID;
65         string stringID;
66         string intID;
67         string booleanID;
68         string shortID;
69         string longID;
70         string floatID;
71         string doubleID;
72         string decimalID;
73         string dateTimeID;
74         string qnameID;
75         string dateID;
76         string timeID;
77         string hexBinaryID;
78         string base64BinaryID;
79         string base64ID;
80         string unsignedByteID;
81         string byteID;
82         string unsignedShortID;
83         string unsignedIntID;
84         string unsignedLongID;
85         string oldDecimalID;
86         string oldTimeInstantID;
87
88         string anyURIID;
89         string durationID;
90         string ENTITYID;
91         string ENTITIESID;
92         string gDayID;
93         string gMonthID;
94         string gMonthDayID;
95         string gYearID;
96         string gYearMonthID;
97         string IDID;
98         string IDREFID;
99         string IDREFSID;
100         string integerID;
101         string languageID;
102         string NameID;
103         string NCNameID;
104         string NMTOKENID;
105         string NMTOKENSID;
106         string negativeIntegerID;
107         string nonPositiveIntegerID;
108         string nonNegativeIntegerID;
109         string normalizedStringID;
110         string NOTATIONID;
111         string positiveIntegerID;
112         string tokenID;
113
114         string charID;
115         string guidID;
116
117         static bool checkDeserializeAdvances;
118 #if CONFIGURATION_DEP
119         static XmlSerializationReader()
120         {
121             XmlSerializerSection configSection = ConfigurationManager.GetSection(ConfigurationStrings.XmlSerializerSectionPath) as XmlSerializerSection;
122             checkDeserializeAdvances = (configSection == null) ? false : configSection.CheckDeserializeAdvances;
123         }
124 #endif
125         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.InitIDs"]/*' />
126         protected abstract void InitIDs();
127
128         // this method must be called before any generated deserialization methods are called
129         internal void Init(XmlReader r, XmlDeserializationEvents events, string encodingStyle, TempAssembly tempAssembly) {
130             this.events = events;
131             if (checkDeserializeAdvances)
132             {
133                 this.countingReader = new XmlCountingReader(r);
134                 this.r = this.countingReader;
135             }
136             else 
137                 this.r = r;
138             this.d = null;
139             this.soap12 = (encodingStyle == Soap12.Encoding);
140             Init(tempAssembly);
141
142             schemaNsID = r.NameTable.Add(XmlSchema.Namespace);
143             schemaNs2000ID = r.NameTable.Add("http://www.w3.org/2000/10/XMLSchema");
144             schemaNs1999ID = r.NameTable.Add("http://www.w3.org/1999/XMLSchema");
145             schemaNonXsdTypesNsID = r.NameTable.Add(UrtTypes.Namespace);
146             instanceNsID = r.NameTable.Add(XmlSchema.InstanceNamespace);
147             instanceNs2000ID = r.NameTable.Add("http://www.w3.org/2000/10/XMLSchema-instance");
148             instanceNs1999ID = r.NameTable.Add("http://www.w3.org/1999/XMLSchema-instance");
149             soapNsID = r.NameTable.Add(Soap.Encoding);
150             soap12NsID = r.NameTable.Add(Soap12.Encoding);
151             schemaID = r.NameTable.Add("schema");
152             wsdlNsID = r.NameTable.Add(Wsdl.Namespace);
153             wsdlArrayTypeID = r.NameTable.Add(Wsdl.ArrayType);
154             nullID = r.NameTable.Add("null");
155             nilID = r.NameTable.Add("nil");
156             typeID = r.NameTable.Add("type");
157             arrayTypeID = r.NameTable.Add("arrayType");
158             itemTypeID = r.NameTable.Add("itemType");
159             arraySizeID = r.NameTable.Add("arraySize");
160             arrayID = r.NameTable.Add("Array");
161             urTypeID = r.NameTable.Add(Soap.UrType);
162             InitIDs();
163         }
164
165         /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.DecodeName"]/*' />
166         protected bool DecodeName {
167             get {
168                 return decodeName;
169             }
170             set {
171                 decodeName = value;
172             }
173         }
174
175         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.Reader"]/*' />
176         protected XmlReader Reader {
177             get {
178                 return r;
179             }
180         }
181
182         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReaderCount"]/*' />
183         protected int ReaderCount {
184             get {
185                 return checkDeserializeAdvances ? countingReader.AdvanceCount : 0;
186             }
187         }
188         
189         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.Document"]/*' />
190         protected XmlDocument Document {
191             get {
192                 if (d == null) {
193                     d = new XmlDocument(r.NameTable);
194                     d.SetBaseURI(r.BaseURI);
195                 }
196                 return d;
197             }
198         }
199
200         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ResolveDynamicAssembly"]/*' />
201         ///<internalonly/>
202         protected static Assembly ResolveDynamicAssembly(string assemblyFullName){
203             return DynamicAssemblies.Get(assemblyFullName);
204         }
205         
206         void InitPrimitiveIDs() {
207             if (tokenID != null) return;
208             object ns = r.NameTable.Add(XmlSchema.Namespace);
209             object ns2 = r.NameTable.Add(UrtTypes.Namespace);
210             
211             stringID = r.NameTable.Add("string");
212             intID = r.NameTable.Add("int");
213             booleanID = r.NameTable.Add("boolean");
214             shortID = r.NameTable.Add("short");
215             longID = r.NameTable.Add("long");
216             floatID = r.NameTable.Add("float");
217             doubleID = r.NameTable.Add("double");
218             decimalID = r.NameTable.Add("decimal");
219             dateTimeID = r.NameTable.Add("dateTime");
220             qnameID = r.NameTable.Add("QName");
221             dateID = r.NameTable.Add("date");
222             timeID = r.NameTable.Add("time");
223             hexBinaryID = r.NameTable.Add("hexBinary");
224             base64BinaryID = r.NameTable.Add("base64Binary");
225             unsignedByteID = r.NameTable.Add("unsignedByte");
226             byteID = r.NameTable.Add("byte");
227             unsignedShortID = r.NameTable.Add("unsignedShort");
228             unsignedIntID = r.NameTable.Add("unsignedInt");
229             unsignedLongID = r.NameTable.Add("unsignedLong");
230             oldDecimalID = r.NameTable.Add("decimal");
231             oldTimeInstantID = r.NameTable.Add("timeInstant");
232             charID = r.NameTable.Add("char");
233             guidID = r.NameTable.Add("guid");
234             base64ID = r.NameTable.Add("base64");
235
236             anyURIID = r.NameTable.Add("anyURI");
237             durationID = r.NameTable.Add("duration");
238             ENTITYID = r.NameTable.Add("ENTITY");
239             ENTITIESID = r.NameTable.Add("ENTITIES");
240             gDayID = r.NameTable.Add("gDay");
241             gMonthID = r.NameTable.Add("gMonth");
242             gMonthDayID = r.NameTable.Add("gMonthDay");
243             gYearID = r.NameTable.Add("gYear");
244             gYearMonthID = r.NameTable.Add("gYearMonth");
245             IDID = r.NameTable.Add("ID");
246             IDREFID = r.NameTable.Add("IDREF");
247             IDREFSID = r.NameTable.Add("IDREFS");
248             integerID = r.NameTable.Add("integer");
249             languageID = r.NameTable.Add("language");
250             NameID = r.NameTable.Add("Name");
251             NCNameID = r.NameTable.Add("NCName");
252             NMTOKENID = r.NameTable.Add("NMTOKEN");
253             NMTOKENSID = r.NameTable.Add("NMTOKENS");
254             negativeIntegerID = r.NameTable.Add("negativeInteger");
255             nonNegativeIntegerID = r.NameTable.Add("nonNegativeInteger");
256             nonPositiveIntegerID = r.NameTable.Add("nonPositiveInteger");
257             normalizedStringID = r.NameTable.Add("normalizedString");
258             NOTATIONID = r.NameTable.Add("NOTATION");
259             positiveIntegerID = r.NameTable.Add("positiveInteger");
260             tokenID = r.NameTable.Add("token");
261         }
262
263         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.GetXsiType"]/*' />
264         /// <devdoc>
265         ///    <para>[To be supplied.]</para>
266         /// </devdoc>
267         protected XmlQualifiedName GetXsiType() {
268             string type = r.GetAttribute(typeID, instanceNsID);
269             if (type == null) {
270                 type = r.GetAttribute(typeID, instanceNs2000ID);
271                 if (type == null) {
272                     type = r.GetAttribute(typeID, instanceNs1999ID);
273                     if (type == null)
274                         return null;
275                 }
276             }
277             return ToXmlQualifiedName(type, false);
278         }
279
280         // throwOnUnknown flag controls whether this method throws an exception or just returns 
281         // null if typeName.Namespace is unknown. the method still throws if typeName.Namespace
282         // is recognized but typeName.Name isn't.
283         Type GetPrimitiveType(XmlQualifiedName typeName, bool throwOnUnknown) {
284             InitPrimitiveIDs();
285
286             if ((object)typeName.Namespace == (object)schemaNsID || (object)typeName.Namespace == (object)soapNsID || (object)typeName.Namespace == (object)soap12NsID) {
287                 if ((object) typeName.Name == (object) stringID ||
288                     (object) typeName.Name == (object) anyURIID ||
289                     (object) typeName.Name == (object) durationID ||
290                     (object) typeName.Name == (object) ENTITYID ||
291                     (object) typeName.Name == (object) ENTITIESID ||
292                     (object) typeName.Name == (object) gDayID ||
293                     (object) typeName.Name == (object) gMonthID ||
294                     (object) typeName.Name == (object) gMonthDayID ||
295                     (object) typeName.Name == (object) gYearID ||
296                     (object) typeName.Name == (object) gYearMonthID ||
297                     (object) typeName.Name == (object) IDID ||
298                     (object) typeName.Name == (object) IDREFID ||
299                     (object) typeName.Name == (object) IDREFSID ||
300                     (object) typeName.Name == (object) integerID ||
301                     (object) typeName.Name == (object) languageID ||
302                     (object) typeName.Name == (object) NameID ||
303                     (object) typeName.Name == (object) NCNameID ||
304                     (object) typeName.Name == (object) NMTOKENID ||
305                     (object) typeName.Name == (object) NMTOKENSID ||
306                     (object) typeName.Name == (object) negativeIntegerID ||
307                     (object) typeName.Name == (object) nonPositiveIntegerID ||
308                     (object) typeName.Name == (object) nonNegativeIntegerID ||
309                     (object) typeName.Name == (object) normalizedStringID ||
310                     (object) typeName.Name == (object) NOTATIONID ||
311                     (object) typeName.Name == (object) positiveIntegerID ||
312                     (object) typeName.Name == (object) tokenID)
313                     return typeof(string);
314                 else if ((object) typeName.Name == (object) intID)
315                     return typeof(int);
316                 else if ((object) typeName.Name == (object) booleanID)
317                     return typeof(bool);
318                 else if ((object) typeName.Name == (object) shortID)
319                     return typeof(short);
320                 else if ((object) typeName.Name == (object) longID)
321                     return typeof(long);
322                 else if ((object) typeName.Name == (object) floatID)
323                     return typeof(float);
324                 else if ((object) typeName.Name == (object) doubleID)
325                     return typeof(double);
326                 else if ((object) typeName.Name == (object) decimalID)
327                     return typeof(decimal);
328                 else if ((object) typeName.Name == (object) dateTimeID)
329                     return typeof(DateTime);
330                 else if ((object) typeName.Name == (object) qnameID)
331                     return typeof(XmlQualifiedName);
332                 else if ((object) typeName.Name == (object) dateID)
333                     return typeof(DateTime);
334                 else if ((object) typeName.Name == (object) timeID)
335                     return typeof(DateTime);
336                 else if ((object) typeName.Name == (object) hexBinaryID)
337                     return typeof(byte[]);
338                 else if ((object)typeName.Name == (object)base64BinaryID)
339                     return typeof(byte[]);
340                 else if ((object)typeName.Name == (object)unsignedByteID)
341                     return typeof(byte);
342                 else if ((object) typeName.Name == (object) byteID)
343                     return typeof(SByte);
344                 else if ((object) typeName.Name == (object) unsignedShortID)
345                     return typeof(UInt16);
346                 else if ((object) typeName.Name == (object) unsignedIntID)
347                     return typeof(UInt32);
348                 else if ((object) typeName.Name == (object) unsignedLongID)
349                     return typeof(UInt64);
350                 else
351                     throw CreateUnknownTypeException(typeName);
352             } 
353             else if ((object) typeName.Namespace == (object) schemaNs2000ID || (object) typeName.Namespace == (object) schemaNs1999ID) {
354                 if ((object) typeName.Name == (object) stringID ||
355                     (object) typeName.Name == (object) anyURIID ||
356                     (object) typeName.Name == (object) durationID ||
357                     (object) typeName.Name == (object) ENTITYID ||
358                     (object) typeName.Name == (object) ENTITIESID ||
359                     (object) typeName.Name == (object) gDayID ||
360                     (object) typeName.Name == (object) gMonthID ||
361                     (object) typeName.Name == (object) gMonthDayID ||
362                     (object) typeName.Name == (object) gYearID ||
363                     (object) typeName.Name == (object) gYearMonthID ||
364                     (object) typeName.Name == (object) IDID ||
365                     (object) typeName.Name == (object) IDREFID ||
366                     (object) typeName.Name == (object) IDREFSID ||
367                     (object) typeName.Name == (object) integerID ||
368                     (object) typeName.Name == (object) languageID ||
369                     (object) typeName.Name == (object) NameID ||
370                     (object) typeName.Name == (object) NCNameID ||
371                     (object) typeName.Name == (object) NMTOKENID ||
372                     (object) typeName.Name == (object) NMTOKENSID ||
373                     (object) typeName.Name == (object) negativeIntegerID ||
374                     (object) typeName.Name == (object) nonPositiveIntegerID ||
375                     (object) typeName.Name == (object) nonNegativeIntegerID ||
376                     (object) typeName.Name == (object) normalizedStringID ||
377                     (object) typeName.Name == (object) NOTATIONID ||
378                     (object) typeName.Name == (object) positiveIntegerID ||
379                     (object) typeName.Name == (object) tokenID)
380                     return typeof(string);
381                 else if ((object) typeName.Name == (object) intID)
382                     return typeof(int);
383                 else if ((object) typeName.Name == (object) booleanID)
384                     return typeof(bool);
385                 else if ((object) typeName.Name == (object) shortID)
386                     return typeof(short);
387                 else if ((object) typeName.Name == (object) longID)
388                     return typeof(long);
389                 else if ((object) typeName.Name == (object) floatID)
390                     return typeof(float);
391                 else if ((object) typeName.Name == (object) doubleID)
392                     return typeof(double);
393                 else if ((object) typeName.Name == (object) oldDecimalID)
394                     return typeof(decimal);
395                 else if ((object) typeName.Name == (object) oldTimeInstantID)
396                     return typeof(DateTime);
397                 else if ((object) typeName.Name == (object) qnameID)
398                     return typeof(XmlQualifiedName);
399                 else if ((object) typeName.Name == (object) dateID)
400                     return typeof(DateTime);
401                 else if ((object) typeName.Name == (object) timeID)
402                     return typeof(DateTime);
403                 else if ((object) typeName.Name == (object) hexBinaryID)
404                     return typeof(byte[]);
405                 else if ((object) typeName.Name == (object) byteID)
406                     return typeof(SByte);
407                 else if ((object) typeName.Name == (object) unsignedShortID)
408                     return typeof(UInt16);
409                 else if ((object) typeName.Name == (object) unsignedIntID)
410                     return typeof(UInt32);
411                 else if ((object) typeName.Name == (object) unsignedLongID)
412                     return typeof(UInt64);
413                 else
414                     throw CreateUnknownTypeException(typeName);
415             }
416             else if ((object) typeName.Namespace == (object) schemaNonXsdTypesNsID) {
417                 if ((object) typeName.Name == (object) charID)
418                     return typeof(char);
419                 else if ((object) typeName.Name == (object) guidID)
420                     return typeof(Guid);
421                 else
422                     throw CreateUnknownTypeException(typeName);
423             }
424             else if (throwOnUnknown)
425                 throw CreateUnknownTypeException(typeName);
426             else
427                 return null;
428         }
429
430         bool IsPrimitiveNamespace(string ns) {
431             return (object) ns == (object) schemaNsID ||
432                    (object) ns == (object) schemaNonXsdTypesNsID ||
433                    (object) ns == (object) soapNsID ||
434                    (object) ns == (object) soap12NsID ||
435                    (object) ns == (object) schemaNs2000ID ||
436                    (object) ns == (object) schemaNs1999ID;
437         }
438
439         private string ReadStringValue(){
440             if (r.IsEmptyElement){
441                 r.Skip();
442                 return string.Empty;
443             }
444             r.ReadStartElement();
445             string retVal = r.ReadString();
446             ReadEndElement();
447             return retVal;
448         }
449
450         private XmlQualifiedName ReadXmlQualifiedName(){
451             string s;
452             bool isEmpty = false;
453             if (r.IsEmptyElement) {
454                 s = string.Empty;
455                 isEmpty = true;
456             }
457             else{
458                 r.ReadStartElement();
459                 s = r.ReadString();
460             }
461             XmlQualifiedName retVal = ToXmlQualifiedName(s);
462             if (isEmpty)
463                 r.Skip();
464             else
465                 ReadEndElement();
466             return retVal;
467         }
468
469         private byte[] ReadByteArray(bool isBase64) {
470             ArrayList list = new ArrayList();
471             const   int MAX_ALLOC_SIZE = 64*1024;
472             int     currentSize = 1024;
473             byte[]  buffer;
474             int     bytes = -1;
475             int     offset = 0;
476             int     total = 0;
477             buffer = new byte[currentSize];
478             list.Add(buffer);
479             while (bytes != 0) {
480                 if (offset == buffer.Length) {
481                     currentSize = Math.Min(currentSize*2, MAX_ALLOC_SIZE);
482                     buffer = new byte[currentSize];
483                     offset = 0;              
484                     list.Add(buffer);
485                 }
486                 if (isBase64) {
487                     bytes = r.ReadElementContentAsBase64(buffer, offset, buffer.Length-offset);
488                 }
489                 else {
490                     bytes = r.ReadElementContentAsBinHex(buffer, offset, buffer.Length-offset);
491                 }
492                 offset += bytes;
493                 total += bytes;
494             }
495
496             byte[] result = new byte[total];
497             offset = 0;
498             foreach (byte[] block in list) {
499                 currentSize = Math.Min(block.Length, total);
500                 if (currentSize > 0) {
501                     Buffer.BlockCopy(block, 0, result, offset, currentSize);
502                     offset += currentSize;
503                     total -= currentSize;
504                 }
505             }
506             list.Clear();
507             return result;
508         }
509
510         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadTypedPrimitive"]/*' />
511         protected object ReadTypedPrimitive(XmlQualifiedName type) {
512             return ReadTypedPrimitive(type, false);
513         }
514
515         private object ReadTypedPrimitive(XmlQualifiedName type, bool elementCanBeType) {
516             InitPrimitiveIDs();
517             object value = null;
518             if (!IsPrimitiveNamespace(type.Namespace) || (object)type.Name == (object)urTypeID) 
519                 return ReadXmlNodes(elementCanBeType);
520
521             if ((object)type.Namespace == (object)schemaNsID || (object)type.Namespace == (object)soapNsID || (object)type.Namespace == (object)soap12NsID) {
522                 if ((object) type.Name == (object) stringID ||
523                     (object) type.Name == (object) normalizedStringID)
524                     value = ReadStringValue();
525                 else if ((object) type.Name == (object) anyURIID ||
526                     (object) type.Name == (object) durationID ||
527                     (object) type.Name == (object) ENTITYID ||
528                     (object) type.Name == (object) ENTITIESID ||
529                     (object) type.Name == (object) gDayID ||
530                     (object) type.Name == (object) gMonthID ||
531                     (object) type.Name == (object) gMonthDayID ||
532                     (object) type.Name == (object) gYearID ||
533                     (object) type.Name == (object) gYearMonthID ||
534                     (object) type.Name == (object) IDID ||
535                     (object) type.Name == (object) IDREFID ||
536                     (object) type.Name == (object) IDREFSID ||
537                     (object) type.Name == (object) integerID ||
538                     (object) type.Name == (object) languageID ||
539                     (object) type.Name == (object) NameID ||
540                     (object) type.Name == (object) NCNameID ||
541                     (object) type.Name == (object) NMTOKENID ||
542                     (object) type.Name == (object) NMTOKENSID ||
543                     (object) type.Name == (object) negativeIntegerID ||
544                     (object) type.Name == (object) nonPositiveIntegerID ||
545                     (object) type.Name == (object) nonNegativeIntegerID ||
546                     (object) type.Name == (object) NOTATIONID ||
547                     (object) type.Name == (object) positiveIntegerID ||
548                     (object) type.Name == (object) tokenID)
549                     value = CollapseWhitespace(ReadStringValue());
550                 else if ((object) type.Name == (object) intID)
551                     value = XmlConvert.ToInt32(ReadStringValue());
552                 else if ((object) type.Name == (object) booleanID)
553                     value = XmlConvert.ToBoolean(ReadStringValue());
554                 else if ((object) type.Name == (object) shortID)
555                     value = XmlConvert.ToInt16(ReadStringValue());
556                 else if ((object) type.Name == (object) longID)
557                     value = XmlConvert.ToInt64(ReadStringValue());
558                 else if ((object)type.Name == (object)floatID)
559                     value = XmlConvert.ToSingle(ReadStringValue());
560                 else if ((object)type.Name == (object)doubleID)
561                     value = XmlConvert.ToDouble(ReadStringValue());
562                 else if ((object)type.Name == (object)decimalID)
563                     value = XmlConvert.ToDecimal(ReadStringValue());
564                 else if ((object)type.Name == (object)dateTimeID)
565                     value = ToDateTime(ReadStringValue());
566                 else if ((object) type.Name == (object) qnameID)
567                     value = ReadXmlQualifiedName();
568                 else if ((object) type.Name == (object) dateID)
569                     value = ToDate(ReadStringValue());
570                 else if ((object) type.Name == (object) timeID)
571                     value = ToTime(ReadStringValue());
572                 else if ((object) type.Name == (object) unsignedByteID)
573                     value = XmlConvert.ToByte(ReadStringValue());
574                 else if ((object) type.Name == (object) byteID)
575                     value = XmlConvert.ToSByte(ReadStringValue());
576                 else if ((object) type.Name == (object) unsignedShortID)
577                     value = XmlConvert.ToUInt16(ReadStringValue());
578                 else if ((object) type.Name == (object) unsignedIntID)
579                     value = XmlConvert.ToUInt32(ReadStringValue());
580                 else if ((object) type.Name == (object) unsignedLongID)
581                     value = XmlConvert.ToUInt64(ReadStringValue());
582                 else if ((object) type.Name == (object) hexBinaryID)
583                     value = ToByteArrayHex(false);
584                 else if ((object) type.Name == (object) base64BinaryID)
585                     value = ToByteArrayBase64(false);
586                 else if ((object) type.Name == (object)base64ID && ((object)type.Namespace == (object)soapNsID || (object)type.Namespace == (object)soap12NsID))
587                     value = ToByteArrayBase64(false);
588                 else
589                     value = ReadXmlNodes(elementCanBeType);
590             }
591             else if ((object) type.Namespace == (object) schemaNs2000ID || (object) type.Namespace == (object) schemaNs1999ID) {
592                 if ((object) type.Name == (object) stringID ||
593                     (object) type.Name == (object) normalizedStringID)
594                     value = ReadStringValue();
595                 else if ((object) type.Name == (object) anyURIID ||
596                     (object) type.Name == (object) anyURIID ||
597                     (object) type.Name == (object) durationID ||
598                     (object) type.Name == (object) ENTITYID ||
599                     (object) type.Name == (object) ENTITIESID ||
600                     (object) type.Name == (object) gDayID ||
601                     (object) type.Name == (object) gMonthID ||
602                     (object) type.Name == (object) gMonthDayID ||
603                     (object) type.Name == (object) gYearID ||
604                     (object) type.Name == (object) gYearMonthID ||
605                     (object) type.Name == (object) IDID ||
606                     (object) type.Name == (object) IDREFID ||
607                     (object) type.Name == (object) IDREFSID ||
608                     (object) type.Name == (object) integerID ||
609                     (object) type.Name == (object) languageID ||
610                     (object) type.Name == (object) NameID ||
611                     (object) type.Name == (object) NCNameID ||
612                     (object) type.Name == (object) NMTOKENID ||
613                     (object) type.Name == (object) NMTOKENSID ||
614                     (object) type.Name == (object) negativeIntegerID ||
615                     (object) type.Name == (object) nonPositiveIntegerID ||
616                     (object) type.Name == (object) nonNegativeIntegerID ||
617                     (object) type.Name == (object) NOTATIONID ||
618                     (object) type.Name == (object) positiveIntegerID ||
619                     (object) type.Name == (object) tokenID)
620                     value = CollapseWhitespace(ReadStringValue());
621                 else if ((object) type.Name == (object) intID)
622                     value = XmlConvert.ToInt32(ReadStringValue());
623                 else if ((object) type.Name == (object) booleanID)
624                     value = XmlConvert.ToBoolean(ReadStringValue());
625                 else if ((object) type.Name == (object) shortID)
626                     value = XmlConvert.ToInt16(ReadStringValue());
627                 else if ((object) type.Name == (object) longID)
628                     value = XmlConvert.ToInt64(ReadStringValue());
629                 else if ((object)type.Name == (object)floatID)
630                     value = XmlConvert.ToSingle(ReadStringValue());
631                 else if ((object)type.Name == (object)doubleID)
632                     value = XmlConvert.ToDouble(ReadStringValue());
633                 else if ((object)type.Name == (object) oldDecimalID)
634                     value = XmlConvert.ToDecimal(ReadStringValue());
635                 else if ((object)type.Name == (object) oldTimeInstantID)
636                     value = ToDateTime(ReadStringValue());
637                 else if ((object) type.Name == (object) qnameID)
638                     value = ReadXmlQualifiedName();
639                 else if ((object) type.Name == (object) dateID)
640                     value = ToDate(ReadStringValue());
641                 else if ((object) type.Name == (object) timeID)
642                     value = ToTime(ReadStringValue());
643                 else if ((object) type.Name == (object) unsignedByteID)
644                     value = XmlConvert.ToByte(ReadStringValue());
645                 else if ((object) type.Name == (object) byteID)
646                     value = XmlConvert.ToSByte(ReadStringValue());
647                 else if ((object) type.Name == (object) unsignedShortID)
648                     value = XmlConvert.ToUInt16(ReadStringValue());
649                 else if ((object) type.Name == (object) unsignedIntID)
650                     value = XmlConvert.ToUInt32(ReadStringValue());
651                 else if ((object) type.Name == (object) unsignedLongID)
652                     value = XmlConvert.ToUInt64(ReadStringValue());
653                 else
654                     value = ReadXmlNodes(elementCanBeType);
655             }
656             else if ((object) type.Namespace == (object) schemaNonXsdTypesNsID) {
657                 if ((object) type.Name == (object) charID)
658                     value = ToChar(ReadStringValue());
659                 else if ((object) type.Name == (object) guidID)
660                     value = new Guid(CollapseWhitespace(ReadStringValue()));
661                 else
662                     value = ReadXmlNodes(elementCanBeType);
663             }
664             else
665                 value = ReadXmlNodes(elementCanBeType);
666             return value;
667         }
668
669         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadTypedNull"]/*' />
670         protected object ReadTypedNull(XmlQualifiedName type) {
671             InitPrimitiveIDs();
672             object value = null;
673             if (!IsPrimitiveNamespace(type.Namespace) || (object)type.Name == (object)urTypeID) {
674                 return null;
675             }
676
677             if ((object)type.Namespace == (object)schemaNsID || (object)type.Namespace == (object)soapNsID || (object)type.Namespace == (object)soap12NsID) {
678                 if ((object) type.Name == (object) stringID ||
679                     (object) type.Name == (object) anyURIID ||
680                     (object) type.Name == (object) durationID ||
681                     (object) type.Name == (object) ENTITYID ||
682                     (object) type.Name == (object) ENTITIESID ||
683                     (object) type.Name == (object) gDayID ||
684                     (object) type.Name == (object) gMonthID ||
685                     (object) type.Name == (object) gMonthDayID ||
686                     (object) type.Name == (object) gYearID ||
687                     (object) type.Name == (object) gYearMonthID ||
688                     (object) type.Name == (object) IDID ||
689                     (object) type.Name == (object) IDREFID ||
690                     (object) type.Name == (object) IDREFSID ||
691                     (object) type.Name == (object) integerID ||
692                     (object) type.Name == (object) languageID ||
693                     (object) type.Name == (object) NameID ||
694                     (object) type.Name == (object) NCNameID ||
695                     (object) type.Name == (object) NMTOKENID ||
696                     (object) type.Name == (object) NMTOKENSID ||
697                     (object) type.Name == (object) negativeIntegerID ||
698                     (object) type.Name == (object) nonPositiveIntegerID ||
699                     (object) type.Name == (object) nonNegativeIntegerID ||
700                     (object) type.Name == (object) normalizedStringID ||
701                     (object) type.Name == (object) NOTATIONID ||
702                     (object) type.Name == (object) positiveIntegerID ||
703                     (object) type.Name == (object) tokenID)
704                     value = null;
705                 else if ((object) type.Name == (object) intID) {
706                     value = default(Nullable<int>);
707                 }
708                 else if ((object) type.Name == (object) booleanID)
709                     value = default(Nullable<bool>);
710                 else if ((object) type.Name == (object) shortID)
711                     value = default(Nullable<Int16>);
712                         else if ((object) type.Name == (object) longID)
713                     value = default(Nullable<long>);
714                 else if ((object)type.Name == (object)floatID)
715                     value = default(Nullable<float>);
716                 else if ((object)type.Name == (object)doubleID)
717                     value = default(Nullable<double>);
718                 else if ((object)type.Name == (object)decimalID)
719                     value = default(Nullable<decimal>);
720                 else if ((object)type.Name == (object)dateTimeID)
721                     value = default(Nullable<DateTime>);
722                         else if ((object) type.Name == (object) qnameID)
723                     value = null;
724                 else if ((object) type.Name == (object) dateID)
725                     value = default(Nullable<DateTime>);
726                         else if ((object) type.Name == (object) timeID)
727                     value = default(Nullable<DateTime>);
728                         else if ((object) type.Name == (object) unsignedByteID)
729                     value = default(Nullable<byte>);
730                 else if ((object) type.Name == (object) byteID)
731                     value = default(Nullable<SByte>);
732                         else if ((object) type.Name == (object) unsignedShortID)
733                     value = default(Nullable<UInt16>);
734                         else if ((object) type.Name == (object) unsignedIntID)
735                     value = default(Nullable<UInt32>);
736                         else if ((object) type.Name == (object) unsignedLongID)
737                     value = default(Nullable<UInt64>);
738                         else if ((object) type.Name == (object) hexBinaryID)
739                     value = null;
740                 else if ((object) type.Name == (object) base64BinaryID)
741                     value = null;
742                 else if ((object) type.Name == (object)base64ID && ((object)type.Namespace == (object)soapNsID || (object)type.Namespace == (object)soap12NsID))
743                     value = null;
744                 else
745                     value = null;
746             }
747             else if ((object) type.Namespace == (object) schemaNonXsdTypesNsID) {
748                 if ((object) type.Name == (object) charID)
749                     value = default(Nullable<char>);
750                 else if ((object) type.Name == (object) guidID)
751                     value = default(Nullable<Guid>);
752                         else
753                     value = null;
754             }
755             else
756                 value = null;
757             return value;
758         }
759
760         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.IsXmlnsAttribute"]/*' />
761         protected bool IsXmlnsAttribute(string name) {
762             if (!name.StartsWith("xmlns", StringComparison.Ordinal)) return false;
763             if (name.Length == 5) return true;
764             return name[5] == ':';
765         }
766
767         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.IsArrayTypeAttribute"]/*' />
768         protected void ParseWsdlArrayType(XmlAttribute attr) {
769             if ((object)attr.LocalName == (object)wsdlArrayTypeID && (object)attr.NamespaceURI == (object)wsdlNsID ) {
770
771                 int colon = attr.Value.LastIndexOf(':');
772                 if (colon < 0) {
773                     attr.Value = r.LookupNamespace("") + ":" + attr.Value;
774                 }
775                 else {
776                     attr.Value = r.LookupNamespace(attr.Value.Substring(0, colon)) + ":" + attr.Value.Substring(colon + 1);
777                 }
778             }
779             return;
780         }
781
782         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.IsReturnValue"]/*' />
783         protected bool IsReturnValue {
784             // value only valid for soap 1.1
785             get { return isReturnValue && !soap12; }
786             set { isReturnValue = value; }
787         }
788
789         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadNull"]/*' />
790         protected bool ReadNull() {
791             if (!GetNullAttr()) return false;
792             if (r.IsEmptyElement) {
793                 r.Skip();
794                 return true;
795             }
796             r.ReadStartElement();
797             int whileIterations = 0;
798             int readerCount = ReaderCount;
799             while (r.NodeType != XmlNodeType.EndElement)
800             {
801                 UnknownNode(null);
802                 CheckReaderCount(ref whileIterations, ref readerCount);
803             }
804             ReadEndElement();
805             return true;
806         }
807
808         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.GetNullAttr"]/*' />
809         protected bool GetNullAttr() {
810             string isNull = r.GetAttribute(nilID, instanceNsID);
811             if(isNull == null)
812                 isNull = r.GetAttribute(nullID, instanceNsID);
813             if (isNull == null) {
814                 isNull = r.GetAttribute(nullID, instanceNs2000ID);
815                 if (isNull == null)
816                     isNull = r.GetAttribute(nullID, instanceNs1999ID);
817             }
818             if (isNull == null || !XmlConvert.ToBoolean(isNull)) return false;
819             return true;
820         }
821
822         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadNullableString"]/*' />
823         protected string ReadNullableString() {
824             if (ReadNull()) return null;
825             return r.ReadElementString();
826         }
827
828         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadNullableQualifiedName"]/*' />
829         /// <devdoc>
830         ///    <para>[To be supplied.]</para>
831         /// </devdoc>
832         protected XmlQualifiedName ReadNullableQualifiedName() {
833             if (ReadNull()) return null;
834             return ReadElementQualifiedName();
835         }
836
837         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadElementQualifiedName"]/*' />
838         /// <devdoc>
839         ///    <para>[To be supplied.]</para>
840         /// </devdoc>
841         protected XmlQualifiedName ReadElementQualifiedName() {
842             if (r.IsEmptyElement) {
843                 XmlQualifiedName empty = new XmlQualifiedName(string.Empty, r.LookupNamespace(""));
844                 r.Skip();
845                 return empty;
846             }
847             XmlQualifiedName qname = ToXmlQualifiedName(CollapseWhitespace(r.ReadString()));
848             r.ReadEndElement();
849             return qname;
850         }
851
852         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadXmlDocument"]/*' />
853         protected XmlDocument ReadXmlDocument(bool wrapped) {
854             XmlNode n = ReadXmlNode(wrapped);
855             if (n == null)
856                 return null;
857             XmlDocument doc = new XmlDocument();
858             doc.AppendChild(doc.ImportNode(n, true));
859             return doc;
860         }
861
862         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CollapseWhitespace"]/*' />
863         protected string CollapseWhitespace(string value) {
864             if (value == null)
865                 return null;
866             return value.Trim();
867         }
868
869         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadXmlNode"]/*' />
870         protected XmlNode ReadXmlNode(bool wrapped) {
871             XmlNode node = null;
872             if (wrapped) {
873                 if (ReadNull()) return null;
874                 r.ReadStartElement();
875                 r.MoveToContent();
876                 if (r.NodeType != XmlNodeType.EndElement)
877                     node = Document.ReadNode(r);
878                 int whileIterations = 0;
879                 int readerCount = ReaderCount;
880                 while (r.NodeType != XmlNodeType.EndElement)
881                 {
882                     UnknownNode(null);
883                     CheckReaderCount(ref whileIterations, ref readerCount);
884                 }
885                 r.ReadEndElement();
886             }
887             else {
888                 node = Document.ReadNode(r);
889             }
890             return node;
891         }
892
893         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToByteArrayBase64"]/*' />
894         protected static byte[] ToByteArrayBase64(string value) {
895             return XmlCustomFormatter.ToByteArrayBase64(value);
896         }
897
898         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToByteArrayBase641"]/*' />
899         protected byte[] ToByteArrayBase64(bool isNull) {
900             if (isNull) {
901                 return null;
902             }
903             return ReadByteArray(true); //means use Base64
904         }
905
906         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToByteArrayHex"]/*' />
907         protected static byte[] ToByteArrayHex(string value) {
908             return XmlCustomFormatter.ToByteArrayHex(value);
909         }
910
911         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToByteArrayHex1"]/*' />
912         protected byte[] ToByteArrayHex(bool isNull) {
913             if (isNull) {
914                 return null;
915             }
916             return ReadByteArray(false); //means use BinHex
917         }
918
919         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.GetArrayLength"]/*' />
920         protected int GetArrayLength(string name, string ns) {
921             if (GetNullAttr()) return 0;
922             string arrayType = r.GetAttribute(arrayTypeID, soapNsID);
923             SoapArrayInfo arrayInfo = ParseArrayType(arrayType);
924             if (arrayInfo.dimensions != 1) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayDimentions, CurrentTag()));
925             XmlQualifiedName qname = ToXmlQualifiedName(arrayInfo.qname, false);
926             if (qname.Name != name) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayTypeName, qname.Name, name, CurrentTag()));
927             if (qname.Namespace != ns) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayTypeNamespace, qname.Namespace, ns, CurrentTag()));
928             return arrayInfo.length;
929         }
930
931         struct SoapArrayInfo {
932             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.qname;"]/*' />
933             public string qname;
934             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.dimensions;"]/*' />
935             public int dimensions;
936             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.length;"]/*' />
937             public int length;
938             public int jaggedDimensions;
939         }
940  
941         private SoapArrayInfo ParseArrayType(string value) {
942             if (value == null) {
943                 throw new ArgumentNullException(Res.GetString(Res.XmlMissingArrayType, CurrentTag()));
944             }
945
946             if (value.Length == 0) {
947                 throw new ArgumentException(Res.GetString(Res.XmlEmptyArrayType, CurrentTag()), "value");
948             }
949  
950             char[] chars = value.ToCharArray();
951             int charsLength = chars.Length;
952         
953             SoapArrayInfo soapArrayInfo = new SoapArrayInfo(); 
954  
955             // Parse backwards to get length first, then optional dimensions, then qname.
956             int pos = charsLength - 1;
957  
958             // Must end with ]
959             if (chars[pos] != ']') {
960                 throw new ArgumentException(Res.GetString(Res.XmlInvalidArraySyntax), "value");
961             }
962             pos--;   
963  
964             // Find [
965             while (pos != -1 && chars[pos] != '[') {
966                 if (chars[pos] == ',')
967                     throw new ArgumentException(Res.GetString(Res.XmlInvalidArrayDimentions, CurrentTag()), "value");
968                 pos--;
969             }
970             if (pos == -1) {
971                 throw new ArgumentException(Res.GetString(Res.XmlMismatchedArrayBrackets), "value");
972             }
973  
974             int len = charsLength - pos - 2;
975             if (len > 0) {
976                 string lengthString = new String(chars, pos + 1, len);
977                 try {
978                     soapArrayInfo.length = Int32.Parse(lengthString, CultureInfo.InvariantCulture);
979                 }
980                 catch (Exception e) {
981                     if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
982                         throw;
983                     }
984                     throw new ArgumentException(Res.GetString(Res.XmlInvalidArrayLength, lengthString), "value");
985                 }
986             }
987             else {
988                 soapArrayInfo.length = -1;
989             }
990
991             pos--;         
992
993             soapArrayInfo.jaggedDimensions = 0;
994             while (pos != -1 && chars[pos] == ']') {
995                 pos--;
996                 if (pos < 0)
997                     throw new ArgumentException(Res.GetString(Res.XmlMismatchedArrayBrackets), "value");
998                 if (chars[pos] == ',')
999                     throw new ArgumentException(Res.GetString(Res.XmlInvalidArrayDimentions, CurrentTag()), "value");
1000                 else if (chars[pos] != '[')
1001                     throw new ArgumentException(Res.GetString(Res.XmlInvalidArraySyntax), "value");
1002                 pos--;
1003                 soapArrayInfo.jaggedDimensions++;
1004             }
1005
1006             soapArrayInfo.dimensions = 1;
1007  
1008             // everything else is qname - validation of qnames?
1009             soapArrayInfo.qname = new String(chars, 0, pos + 1);
1010             return soapArrayInfo;
1011         }
1012
1013         private SoapArrayInfo ParseSoap12ArrayType(string itemType, string arraySize) {
1014             SoapArrayInfo soapArrayInfo = new SoapArrayInfo(); 
1015
1016             if (itemType != null && itemType.Length > 0)
1017                 soapArrayInfo.qname = itemType;
1018             else
1019                 soapArrayInfo.qname = "";
1020
1021             string[] dimensions;
1022             if (arraySize != null && arraySize.Length > 0)
1023                 dimensions = arraySize.Split(null);
1024             else
1025                 dimensions = new string[0];
1026
1027             soapArrayInfo.dimensions = 0;
1028             soapArrayInfo.length = -1;
1029             for (int i = 0; i < dimensions.Length; i++) {
1030                 if (dimensions[i].Length > 0) {
1031                     if (dimensions[i] == "*") {
1032                         soapArrayInfo.dimensions++;
1033                     }
1034                     else {
1035                         try {
1036                             soapArrayInfo.length = Int32.Parse(dimensions[i], CultureInfo.InvariantCulture);
1037                             soapArrayInfo.dimensions++;
1038                         }
1039                         catch (Exception e) {
1040                             if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
1041                                 throw;
1042                             }
1043                             throw new ArgumentException(Res.GetString(Res.XmlInvalidArrayLength, dimensions[i]), "value");
1044                         }
1045                     }
1046                 }
1047             }
1048             if (soapArrayInfo.dimensions == 0)
1049                 soapArrayInfo.dimensions = 1; // default is 1D even if no arraySize is specified
1050
1051             return soapArrayInfo;
1052         }
1053
1054         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToDateTime"]/*' />
1055         protected static DateTime ToDateTime(string value) {
1056             return XmlCustomFormatter.ToDateTime(value);
1057         }
1058
1059         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToDate"]/*' />
1060         protected static DateTime ToDate(string value) {
1061             return XmlCustomFormatter.ToDate(value);
1062         }
1063
1064         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToTime"]/*' />
1065         protected static DateTime ToTime(string value) {
1066             return XmlCustomFormatter.ToTime(value);
1067         }
1068
1069         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToChar"]/*' />
1070         protected static char ToChar(string value) {
1071             return XmlCustomFormatter.ToChar(value);
1072         }
1073
1074         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToEnum"]/*' />
1075         protected static long ToEnum(string value, Hashtable h, string typeName) {
1076             return XmlCustomFormatter.ToEnum(value, h, typeName, true);
1077         }
1078
1079         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToXmlName"]/*' />
1080         protected static string ToXmlName(string value) {
1081             return XmlCustomFormatter.ToXmlName(value);
1082         }
1083
1084         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToXmlNCName"]/*' />
1085         protected static string ToXmlNCName(string value) {
1086             return XmlCustomFormatter.ToXmlNCName(value);
1087         }
1088         
1089         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToXmlNmToken"]/*' />
1090         protected static string ToXmlNmToken(string value) {
1091             return XmlCustomFormatter.ToXmlNmToken(value);
1092         }
1093         
1094         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToXmlNmTokens"]/*' />
1095         protected static string ToXmlNmTokens(string value) {
1096             return XmlCustomFormatter.ToXmlNmTokens(value);
1097         }
1098         
1099         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ToXmlQualifiedName"]/*' />
1100         protected XmlQualifiedName ToXmlQualifiedName(string value) {
1101             return ToXmlQualifiedName(value, DecodeName);
1102         }
1103
1104         internal XmlQualifiedName ToXmlQualifiedName(string value, bool decodeName) {
1105             int colon = value == null ? -1 : value.LastIndexOf(':');
1106             string prefix = colon < 0 ? null : value.Substring(0, colon);
1107             string localName = value.Substring(colon + 1);
1108
1109             if (decodeName) {
1110                 prefix = XmlConvert.DecodeName(prefix);
1111                 localName = XmlConvert.DecodeName(localName);
1112             }
1113             if (prefix == null || prefix.Length == 0) {
1114                 return new XmlQualifiedName(r.NameTable.Add(value), r.LookupNamespace(String.Empty));
1115             }
1116             else {
1117                 string ns = r.LookupNamespace(prefix);
1118                 if (ns == null) {
1119                     // Namespace prefix '{0}' is not defined.
1120                     throw new InvalidOperationException(Res.GetString(Res.XmlUndefinedAlias, prefix));
1121                 }
1122                 return new XmlQualifiedName(r.NameTable.Add(localName), ns);
1123             }
1124         }
1125         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownAttribute"]/*' />
1126         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownAttribute"]/*' />
1127         protected void UnknownAttribute(object o, XmlAttribute attr) {
1128             UnknownAttribute(o, attr, null);
1129         }
1130
1131         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownAttribute1"]/*' />
1132         protected void UnknownAttribute(object o, XmlAttribute attr, string qnames) {
1133             if (events.OnUnknownAttribute != null) {
1134                 int lineNumber, linePosition;
1135                 GetCurrentPosition(out lineNumber, out linePosition);
1136                 XmlAttributeEventArgs e = new XmlAttributeEventArgs(attr, lineNumber, linePosition, o, qnames);
1137                 events.OnUnknownAttribute(events.sender, e);
1138             }
1139         }
1140
1141         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownAttribute"]/*' />
1142         protected void UnknownElement(object o, XmlElement elem) {
1143             UnknownElement(o, elem, null);
1144         }
1145
1146         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownElement1"]/*' />
1147         protected void UnknownElement(object o, XmlElement elem, string qnames) {
1148             if (events.OnUnknownElement != null) {
1149                 int lineNumber, linePosition;
1150                 GetCurrentPosition(out lineNumber, out linePosition);
1151                 XmlElementEventArgs e = new XmlElementEventArgs(elem, lineNumber, linePosition, o, qnames);
1152                 events.OnUnknownElement(events.sender, e);
1153             }
1154         }
1155
1156         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownNode"]/*' />
1157         protected void UnknownNode(object o) {
1158             UnknownNode(o, null);
1159         }
1160
1161         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnknownNode1"]/*' />
1162         protected void UnknownNode(object o, string qnames) {
1163             if (r.NodeType == XmlNodeType.None || r.NodeType == XmlNodeType.Whitespace) {
1164                 r.Read();
1165                 return;
1166             }
1167             if (r.NodeType == XmlNodeType.EndElement)
1168                 return;
1169             if (events.OnUnknownNode != null) {
1170                 UnknownNode(Document.ReadNode(r), o, qnames);
1171             }
1172             else if (r.NodeType == XmlNodeType.Attribute && events.OnUnknownAttribute == null) {
1173                 return;
1174             }
1175             else if (r.NodeType == XmlNodeType.Element && events.OnUnknownElement == null) {
1176                 r.Skip();
1177                 return;
1178             }
1179             else {
1180                 UnknownNode(Document.ReadNode(r), o, qnames);
1181             }
1182         }
1183
1184         void UnknownNode(XmlNode unknownNode, object o, string qnames) {
1185             if (unknownNode == null)
1186                 return;
1187             if (unknownNode.NodeType != XmlNodeType.None && unknownNode.NodeType != XmlNodeType.Whitespace && events.OnUnknownNode != null) {
1188                 int lineNumber, linePosition;
1189                 GetCurrentPosition(out lineNumber, out linePosition);
1190                 XmlNodeEventArgs e = new XmlNodeEventArgs(unknownNode, lineNumber, linePosition, o);
1191                 events.OnUnknownNode(events.sender, e);
1192             }
1193             if (unknownNode.NodeType == XmlNodeType.Attribute) {
1194                 UnknownAttribute(o, (XmlAttribute)unknownNode, qnames);
1195             }
1196             else if (unknownNode.NodeType == XmlNodeType.Element) {
1197                 UnknownElement(o, (XmlElement)unknownNode, qnames);
1198             }
1199         }
1200
1201
1202         void GetCurrentPosition(out int lineNumber, out int linePosition){
1203             if (Reader is IXmlLineInfo){
1204                 IXmlLineInfo lineInfo = (IXmlLineInfo)Reader;
1205                 lineNumber = lineInfo.LineNumber;
1206                 linePosition = lineInfo.LinePosition;
1207             }
1208             else
1209                 lineNumber = linePosition = -1;
1210         }
1211
1212         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.UnreferencedObject"]/*' />
1213         protected void UnreferencedObject(string id, object o) {
1214             if (events.OnUnreferencedObject != null) {
1215                 UnreferencedObjectEventArgs e = new UnreferencedObjectEventArgs(o, id);
1216                 events.OnUnreferencedObject(events.sender, e);
1217             }
1218         }
1219
1220         string CurrentTag() {
1221             switch (r.NodeType) {
1222                 case XmlNodeType.Element:
1223                     return "<" + r.LocalName + " xmlns='" + r.NamespaceURI + "'>";
1224                 case XmlNodeType.EndElement:
1225                     return ">";
1226                 case XmlNodeType.Text:
1227                     return r.Value;
1228                 case XmlNodeType.CDATA:
1229                     return "CDATA";
1230                 case XmlNodeType.Comment:
1231                     return "<--";
1232                 case XmlNodeType.ProcessingInstruction:
1233                     return "<?";
1234                 default:
1235                     return "(unknown)";
1236             }
1237         }
1238
1239         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateUnknownTypeException"]/*' />
1240         protected Exception CreateUnknownTypeException(XmlQualifiedName type) {
1241             return new InvalidOperationException(Res.GetString(Res.XmlUnknownType, type.Name, type.Namespace, CurrentTag()));
1242         }
1243
1244         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateReadOnlyCollectionException"]/*' />
1245         protected Exception CreateReadOnlyCollectionException(string name) {
1246             return new InvalidOperationException(Res.GetString(Res.XmlReadOnlyCollection, name));
1247         }
1248
1249         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateAbstractTypeException"]/*' />
1250         protected Exception CreateAbstractTypeException(string name, string ns) {
1251             return new InvalidOperationException(Res.GetString(Res.XmlAbstractType, name, ns, CurrentTag()));
1252         }
1253
1254         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateInaccessibleConstructorException"]/*' />
1255         protected Exception CreateInaccessibleConstructorException(string typeName) {
1256             return new InvalidOperationException(Res.GetString(Res.XmlConstructorInaccessible, typeName));
1257         }
1258
1259         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateCtorHasSecurityException"]/*' />
1260         protected Exception CreateCtorHasSecurityException(string typeName) {
1261             return new InvalidOperationException(Res.GetString(Res.XmlConstructorHasSecurityAttributes, typeName));
1262         }
1263
1264         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateUnknownNodeException"]/*' />
1265         protected Exception CreateUnknownNodeException() {
1266             return new InvalidOperationException(Res.GetString(Res.XmlUnknownNode, CurrentTag()));
1267         }
1268
1269         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateUnknownConstantException"]/*' />
1270         protected Exception CreateUnknownConstantException(string value, Type enumType) {
1271             return new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, value, enumType.Name));
1272         }
1273
1274         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateInvalidCastException"]/*' />
1275         protected Exception CreateInvalidCastException(Type type, object value) {
1276             return CreateInvalidCastException(type, value, null);
1277         }
1278
1279         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateInvalidCastException1"]/*' />
1280         protected Exception CreateInvalidCastException(Type type, object value, string id) {
1281             if (value == null)
1282                 return new InvalidCastException(Res.GetString(Res.XmlInvalidNullCast, type.FullName));
1283             else if (id == null)
1284                 return new InvalidCastException(Res.GetString(Res.XmlInvalidCast, value.GetType().FullName, type.FullName));
1285             else
1286                 return new InvalidCastException(Res.GetString(Res.XmlInvalidCastWithId, value.GetType().FullName, type.FullName, id));
1287
1288         }
1289
1290         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateBadDerivationException"]/*' />
1291         protected Exception CreateBadDerivationException(string xsdDerived, string nsDerived, string xsdBase, string nsBase, string clrDerived, string clrBase) {
1292             return new InvalidOperationException(Res.GetString(Res.XmlSerializableBadDerivation, xsdDerived, nsDerived, xsdBase, nsBase, clrDerived, clrBase));
1293         }
1294
1295         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CreateMissingIXmlSerializableType"]/*' />
1296         protected Exception CreateMissingIXmlSerializableType(string name, string ns, string clrType) {
1297             return new InvalidOperationException(Res.GetString(Res.XmlSerializableMissingClrType, name, ns, typeof(XmlIncludeAttribute).Name, clrType));
1298             //XmlSerializableMissingClrType= Type '{0}' from namespace '{1}' doesnot have corresponding IXmlSerializable type. Please consider adding {2} to '{3}'.
1299         }
1300
1301         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.EnsureArrayIndex"]/*' />
1302         protected Array EnsureArrayIndex(Array a, int index, Type elementType) {
1303             if (a == null) return Array.CreateInstance(elementType, 32);
1304             if (index < a.Length) return a;
1305             Array b = Array.CreateInstance(elementType, a.Length * 2);
1306             Array.Copy(a, b, index);
1307             return b;
1308         }
1309
1310         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ShrinkArray"]/*' />
1311         protected Array ShrinkArray(Array a, int length, Type elementType, bool isNullable) {
1312             if (a == null) {
1313                 if (isNullable) return null;
1314                 return Array.CreateInstance(elementType, 0);
1315             }
1316             if (a.Length == length) return a;
1317             Array b = Array.CreateInstance(elementType, length);
1318             Array.Copy(a, b, length);
1319             return b;
1320         } 
1321
1322         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadString"]/*' />
1323         protected string ReadString(string value) {
1324             return ReadString(value, false);
1325         }
1326
1327         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadString1"]/*' />
1328         protected string ReadString(string value, bool trim) {
1329             string str = r.ReadString();
1330             if (str != null && trim)
1331                 str = str.Trim();
1332             if (value == null || value.Length == 0)
1333                 return str;
1334             return value + str;
1335         }
1336
1337         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadSerializable"]/*' />
1338         protected IXmlSerializable ReadSerializable(IXmlSerializable serializable) {
1339             return ReadSerializable(serializable, false);
1340         }
1341
1342         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadSerializable"]/*' />
1343         protected IXmlSerializable ReadSerializable(IXmlSerializable serializable, bool wrappedAny)
1344         {
1345             string name = null;
1346             string ns = null;
1347
1348             if (wrappedAny) {
1349                 name = r.LocalName;
1350                 ns = r.NamespaceURI;
1351                 r.Read();
1352                 r.MoveToContent();
1353             }
1354             serializable.ReadXml(r);
1355
1356             if (wrappedAny) {
1357                 while (r.NodeType == XmlNodeType.Whitespace) r.Skip();
1358                 if (r.NodeType == XmlNodeType.None) r.Skip();
1359                 if (r.NodeType == XmlNodeType.EndElement && r.LocalName == name && r.NamespaceURI == ns) {
1360                     Reader.Read();
1361                 }
1362             }
1363             return serializable;
1364         }
1365
1366         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReference"]/*' />
1367         protected bool ReadReference(out string fixupReference) {
1368             string href = soap12 ? r.GetAttribute("ref", Soap12.Encoding) : r.GetAttribute("href");
1369             if (href == null) {
1370                 fixupReference = null;
1371                 return false;
1372             }
1373             if (!soap12) {
1374                 // soap 1.1 href starts with '#'; soap 1.2 ref does not
1375                 if (!href.StartsWith("#", StringComparison.Ordinal)) throw new InvalidOperationException(Res.GetString(Res.XmlMissingHref, href));
1376                 fixupReference = href.Substring(1);
1377             }
1378             else
1379                 fixupReference = href;
1380
1381             if (r.IsEmptyElement) {
1382                 r.Skip();
1383             }
1384             else {
1385                 r.ReadStartElement();
1386                 ReadEndElement();
1387             }
1388             return true;
1389         }
1390
1391         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.AddTarget"]/*' />
1392         protected void AddTarget(string id, object o) {
1393             if (id == null) {
1394                 if (targetsWithoutIds == null) 
1395                     targetsWithoutIds = new ArrayList();
1396                 if (o != null) 
1397                     targetsWithoutIds.Add(o);
1398             }
1399             else {
1400                 if (targets == null) targets = new Hashtable();
1401                 if (!targets.Contains(id))
1402                     targets.Add(id, o);
1403             }
1404         }
1405
1406
1407
1408         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.AddFixup"]/*' />
1409         protected void AddFixup(Fixup fixup) {
1410             if (fixups == null) fixups = new ArrayList();
1411             fixups.Add(fixup);
1412         }
1413
1414         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.AddFixup2"]/*' />
1415         protected void AddFixup(CollectionFixup fixup) {
1416             if (collectionFixups == null) collectionFixups = new ArrayList();
1417             collectionFixups.Add(fixup);
1418         }
1419
1420         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.GetTarget"]/*' />
1421         protected object GetTarget(string id) {
1422             object target = targets != null ? targets[id] : null;
1423             if (target == null) {
1424                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidHref, id));
1425             }
1426             Referenced(target);
1427             return target;
1428         }
1429
1430         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.Referenced"]/*' />
1431         protected void Referenced(object o) {
1432             if (o == null) return;
1433             if (referencedTargets == null) referencedTargets = new Hashtable();
1434             referencedTargets[o] = o;
1435         }
1436
1437         void HandleUnreferencedObjects() {
1438             if (targets != null) {
1439                 foreach (DictionaryEntry target in targets) {
1440                     if (referencedTargets == null || !referencedTargets.Contains(target.Value)) {
1441                         UnreferencedObject((string)target.Key, target.Value);
1442                     }
1443                 }
1444             }
1445             if (targetsWithoutIds != null) {
1446                 foreach (object o in targetsWithoutIds) {
1447                     if (referencedTargets == null || !referencedTargets.Contains(o)) {
1448                         UnreferencedObject(null, o);
1449                     }
1450                 }
1451             }
1452         }
1453
1454         void DoFixups() {
1455             if (fixups == null) return;
1456             for (int i = 0; i < fixups.Count; i++) {
1457                 Fixup fixup = (Fixup)fixups[i];
1458                 fixup.Callback(fixup);
1459             }
1460
1461             if (collectionFixups == null) return;
1462             for (int i = 0; i < collectionFixups.Count; i++) {
1463                 CollectionFixup collectionFixup = (CollectionFixup)collectionFixups[i];
1464                 collectionFixup.Callback(collectionFixup.Collection, collectionFixup.CollectionItems);
1465             }
1466         }
1467
1468         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.FixupArrayRefs"]/*' />
1469         protected void FixupArrayRefs(object fixup) {
1470             Fixup f = (Fixup)fixup;
1471             Array array = (Array)f.Source;
1472             for (int i = 0; i < array.Length; i++) {
1473                 string id = f.Ids[i];
1474                 if (id == null) continue;
1475                 object o = GetTarget(id);
1476                 try {
1477                     array.SetValue(o, i);
1478                 }
1479                 catch (InvalidCastException) {
1480                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayRef, id, o.GetType().FullName, i.ToString(CultureInfo.InvariantCulture)));
1481                 }
1482             }
1483         }
1484
1485         object ReadArray(string typeName, string typeNs) {
1486             SoapArrayInfo arrayInfo;
1487             Type fallbackElementType = null;
1488             if (soap12) {
1489                 string itemType = r.GetAttribute(itemTypeID, soap12NsID);
1490                 string arraySize = r.GetAttribute(arraySizeID, soap12NsID);
1491                 Type arrayType = (Type)types[new XmlQualifiedName(typeName, typeNs)];
1492                 // no indication that this is an array?
1493                 if (itemType == null && arraySize == null && (arrayType == null || !arrayType.IsArray))
1494                     return null;
1495
1496                 arrayInfo = ParseSoap12ArrayType(itemType, arraySize);
1497                 if (arrayType != null)
1498                     fallbackElementType = TypeScope.GetArrayElementType(arrayType, null);
1499             }
1500             else {
1501                 string arrayType = r.GetAttribute(arrayTypeID, soapNsID);
1502                 if (arrayType == null) 
1503                     return null;
1504
1505                 arrayInfo = ParseArrayType(arrayType);
1506             }
1507
1508             if (arrayInfo.dimensions != 1) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayDimentions, CurrentTag()));
1509
1510             // NOTE: don't use the array size that is specified since an evil client might pass
1511             // a number larger than the actual number of items in an attempt to harm the server.
1512
1513             XmlQualifiedName qname;
1514             bool isPrimitive;
1515             Type elementType = null;
1516             XmlQualifiedName urTypeName = new XmlQualifiedName(urTypeID, schemaNsID);
1517             if (arrayInfo.qname.Length > 0) {
1518                 qname = ToXmlQualifiedName(arrayInfo.qname, false);
1519                 elementType = (Type)types[qname];
1520             }
1521             else
1522                 qname = urTypeName;
1523             
1524             // try again if the best we could come up with was object
1525             if (soap12 && elementType == typeof(object))
1526                 elementType = null;
1527             
1528             if (elementType == null) {
1529                 if (!soap12) {
1530                     elementType = GetPrimitiveType(qname, true);
1531                     isPrimitive = true;
1532                 }
1533                 else {
1534                     // try it as a primitive
1535                     if (qname != urTypeName)
1536                         elementType = GetPrimitiveType(qname, false);
1537                     if (elementType != null) {
1538                         isPrimitive = true;
1539                     }
1540                     else {
1541                         // still nothing: go with fallback type or object
1542                         if (fallbackElementType == null) {
1543                             elementType = typeof(object);
1544                             isPrimitive = false;
1545                         }
1546                         else {
1547                             elementType = fallbackElementType;
1548                             XmlQualifiedName newQname = (XmlQualifiedName)typesReverse[elementType];
1549                             if (newQname == null) {
1550                                 newQname = XmlSerializationWriter.GetPrimitiveTypeNameInternal(elementType);
1551                                 isPrimitive = true;
1552                             }
1553                             else
1554                                 isPrimitive = elementType.IsPrimitive;
1555                             if (newQname != null) qname = newQname;
1556                         }
1557                     }
1558                 }
1559             }
1560             else
1561                 isPrimitive = elementType.IsPrimitive;
1562
1563             if (!soap12 && arrayInfo.jaggedDimensions > 0) {
1564                 for (int i = 0; i < arrayInfo.jaggedDimensions; i++)
1565                     elementType = elementType.MakeArrayType();
1566             }
1567
1568             if (r.IsEmptyElement) {
1569                 r.Skip();
1570                 return Array.CreateInstance(elementType, 0);
1571             }
1572
1573             r.ReadStartElement();
1574             r.MoveToContent();
1575
1576             int arrayLength = 0;
1577             Array array = null;
1578
1579             if (elementType.IsValueType) {
1580                 if (!isPrimitive && !elementType.IsEnum) {
1581                     throw new NotSupportedException(Res.GetString(Res.XmlRpcArrayOfValueTypes, elementType.FullName));
1582                 }
1583                 // 
1584
1585                 int whileIterations = 0;
1586                 int readerCount = ReaderCount;
1587                 while (r.NodeType != XmlNodeType.EndElement) {
1588                     array = EnsureArrayIndex(array, arrayLength, elementType);
1589                     array.SetValue(ReadReferencedElement(qname.Name, qname.Namespace), arrayLength);
1590                     arrayLength++;
1591                     r.MoveToContent();
1592                     CheckReaderCount(ref whileIterations, ref readerCount);
1593                 }
1594                 array = ShrinkArray(array, arrayLength, elementType, false);
1595             }
1596             else {
1597                 string type;
1598                 string typens;
1599                 string[] ids = null;
1600                 int idsLength = 0;
1601
1602                 int whileIterations = 0;
1603                 int readerCount = ReaderCount;
1604                 while (r.NodeType != XmlNodeType.EndElement) {
1605                     array = EnsureArrayIndex(array, arrayLength, elementType);
1606                     ids = (string[])EnsureArrayIndex(ids, idsLength, typeof(string));
1607                     // 
1608                     if (r.NamespaceURI.Length != 0){
1609                         type = r.LocalName;
1610                         if ((object)r.NamespaceURI == (object)soapNsID)
1611                             typens = XmlSchema.Namespace;
1612                         else
1613                             typens = r.NamespaceURI;
1614                     }
1615                     else {
1616                         type = qname.Name;
1617                         typens = qname.Namespace;                        
1618                     }
1619                     array.SetValue(ReadReferencingElement(type, typens, out ids[idsLength]), arrayLength);
1620                     arrayLength++;
1621                     idsLength++;
1622                     // 
1623                     r.MoveToContent();
1624                     CheckReaderCount(ref whileIterations, ref readerCount);
1625                 }
1626
1627                 // special case for soap 1.2: try to get a better fit than object[] when no metadata is known
1628                 // this applies in the doc/enc/bare case
1629                 if (soap12 && elementType == typeof(object)) {
1630                     Type itemType = null;
1631                     for (int i = 0; i < arrayLength; i++) {
1632                         object currItem = array.GetValue(i);
1633                         if (currItem != null) {
1634                             Type currItemType = currItem.GetType();
1635                             if (currItemType.IsValueType) {
1636                                 itemType = null;
1637                                 break;
1638                             }
1639                             if (itemType == null || currItemType.IsAssignableFrom(itemType)) {
1640                                 itemType = currItemType;
1641                             }
1642                             else if (!itemType.IsAssignableFrom(currItemType)) {
1643                                 itemType = null;
1644                                 break;
1645                             }
1646                         }
1647                     }
1648                     if (itemType != null)
1649                         elementType = itemType;
1650                 }
1651                 ids = (string[])ShrinkArray(ids, idsLength, typeof(string), false);
1652                 array = ShrinkArray(array, arrayLength, elementType, false);
1653                 Fixup fixupArray = new Fixup(array, new XmlSerializationFixupCallback(this.FixupArrayRefs), ids);
1654                 AddFixup(fixupArray);
1655             }
1656
1657             // 
1658
1659             ReadEndElement();
1660             return array;
1661         }
1662
1663         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.InitCallbacks"]/*' />
1664         protected abstract void InitCallbacks();
1665
1666         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencedElements"]/*' />
1667         protected void ReadReferencedElements() {
1668             r.MoveToContent();
1669             string dummy;
1670             int whileIterations = 0;
1671             int readerCount = ReaderCount;
1672             while (r.NodeType != XmlNodeType.EndElement && r.NodeType != XmlNodeType.None) {
1673                 ReadReferencingElement(null, null, true, out dummy);
1674                 r.MoveToContent();
1675                 CheckReaderCount(ref whileIterations, ref readerCount);
1676             }
1677             DoFixups();
1678
1679             HandleUnreferencedObjects();
1680         }
1681
1682         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencedElement"]/*' />
1683         protected object ReadReferencedElement() {
1684             return ReadReferencedElement(null, null);
1685         }
1686
1687         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencedElement1"]/*' />
1688         protected object ReadReferencedElement(string name, string ns) {
1689             string dummy;
1690             return ReadReferencingElement(name, ns, out dummy);
1691         }
1692
1693         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencingElement"]/*' />
1694         protected object ReadReferencingElement(out string fixupReference) {
1695             return ReadReferencingElement(null, null, out fixupReference);
1696         }
1697
1698         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencingElement1"]/*' />
1699         protected object ReadReferencingElement(string name, string ns, out string fixupReference) {
1700             return ReadReferencingElement(name, ns, false, out fixupReference);
1701         }
1702
1703         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadReferencingElement2"]/*' />
1704         protected object ReadReferencingElement(string name, string ns, bool elementCanBeType, out string fixupReference) {
1705             object o = null;
1706
1707             if (callbacks == null) {
1708                 callbacks = new Hashtable();
1709                 types = new Hashtable();
1710                 XmlQualifiedName urType = new XmlQualifiedName(urTypeID, r.NameTable.Add(XmlSchema.Namespace));
1711                 types.Add(urType, typeof(object));
1712                 typesReverse = new Hashtable();
1713                 typesReverse.Add(typeof(object), urType);
1714                 InitCallbacks();
1715             }
1716
1717             r.MoveToContent();
1718
1719             if (ReadReference(out fixupReference)) return null;
1720
1721             if (ReadNull()) return null;
1722
1723             string id = soap12 ? r.GetAttribute("id", Soap12.Encoding) : r.GetAttribute("id", null);
1724
1725             if ((o = ReadArray(name, ns)) == null) {
1726                 XmlQualifiedName typeId = GetXsiType();
1727                 if (typeId == null) {
1728                     if (name == null)
1729                         typeId = new XmlQualifiedName(r.NameTable.Add(r.LocalName), r.NameTable.Add(r.NamespaceURI));
1730                     else
1731                         typeId = new XmlQualifiedName(r.NameTable.Add(name), r.NameTable.Add(ns));
1732                 }
1733                 XmlSerializationReadCallback callback = (XmlSerializationReadCallback)callbacks[typeId];
1734                 if (callback != null) {
1735                     o = callback();
1736                 }
1737                 else
1738                     o = ReadTypedPrimitive(typeId, elementCanBeType);
1739             }
1740
1741             AddTarget(id, o);
1742
1743             return o;
1744         }
1745
1746         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.AddReadCallback"]/*' />
1747         protected void AddReadCallback(string name, string ns, Type type, XmlSerializationReadCallback read) {
1748             XmlQualifiedName typeName = new XmlQualifiedName(r.NameTable.Add(name), r.NameTable.Add(ns));
1749             callbacks[typeName] = read;
1750             types[typeName] = type;
1751             typesReverse[type] = typeName;
1752         }
1753
1754         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.ReadEndElement"]/*' />
1755         protected void ReadEndElement() {
1756             while (r.NodeType == XmlNodeType.Whitespace) r.Skip();
1757             if (r.NodeType == XmlNodeType.None) r.Skip();
1758             else r.ReadEndElement();
1759         }
1760
1761         object ReadXmlNodes(bool elementCanBeType) {
1762
1763             ArrayList xmlNodeList = new ArrayList();
1764             string elemLocalName = Reader.LocalName;
1765             string elemNs = Reader.NamespaceURI;
1766             string elemName = Reader.Name;
1767             string xsiTypeName = null;
1768             string xsiTypeNs = null;
1769             int skippableNodeCount = 0;
1770             int lineNumber = -1, linePosition=-1;
1771             XmlNode unknownNode = null;
1772             if(Reader.NodeType == XmlNodeType.Attribute){
1773                 XmlAttribute attr = Document.CreateAttribute(elemName, elemNs);
1774                 attr.Value = Reader.Value;
1775                 unknownNode = attr;
1776             }
1777             else
1778                 unknownNode = Document.CreateElement(elemName, elemNs);
1779             GetCurrentPosition(out lineNumber, out linePosition);
1780             XmlElement unknownElement = unknownNode as XmlElement;
1781
1782             while (Reader.MoveToNextAttribute()) {
1783                 if (IsXmlnsAttribute(Reader.Name) || (Reader.Name == "id" && (!soap12 || Reader.NamespaceURI == Soap12.Encoding)))
1784                     skippableNodeCount++;
1785                 if ( (object)Reader.LocalName == (object)typeID &&
1786                      ( (object)Reader.NamespaceURI == (object)instanceNsID ||
1787                        (object)Reader.NamespaceURI == (object)instanceNs2000ID ||
1788                        (object)Reader.NamespaceURI == (object)instanceNs1999ID
1789                      )
1790                    ){
1791                     string value = Reader.Value;
1792                     int colon = value.LastIndexOf(':');
1793                     xsiTypeName = (colon >= 0) ? value.Substring(colon+1) : value;
1794                     xsiTypeNs = Reader.LookupNamespace((colon >= 0) ? value.Substring(0, colon) : "");
1795                 }
1796                 XmlAttribute xmlAttribute = (XmlAttribute)Document.ReadNode(r);
1797                 xmlNodeList.Add(xmlAttribute);
1798                 if (unknownElement != null) unknownElement.SetAttributeNode(xmlAttribute);
1799             }
1800
1801             // If the node is referenced (or in case of paramStyle = bare) and if xsi:type is not
1802             // specified then the element name is used as the type name. Reveal this to the user
1803             // by adding an extra attribute node "xsi:type" with value as the element name.
1804             if(elementCanBeType && xsiTypeName == null){
1805                 xsiTypeName = elemLocalName;
1806                 xsiTypeNs = elemNs;
1807                 XmlAttribute xsiTypeAttribute = Document.CreateAttribute(typeID, instanceNsID);
1808                 xsiTypeAttribute.Value = elemName;
1809                 xmlNodeList.Add(xsiTypeAttribute);
1810             }
1811             if( xsiTypeName == Soap.UrType &&
1812                 ( (object)xsiTypeNs == (object)schemaNsID ||
1813                   (object)xsiTypeNs == (object)schemaNs1999ID ||
1814                   (object)xsiTypeNs == (object)schemaNs2000ID
1815                 )
1816                )
1817                 skippableNodeCount++;
1818             
1819             
1820             Reader.MoveToElement();
1821             if (Reader.IsEmptyElement) {
1822                 Reader.Skip();
1823             }
1824             else {
1825                 Reader.ReadStartElement();
1826                 Reader.MoveToContent();
1827                 int whileIterations = 0;
1828                 int readerCount = ReaderCount;
1829                 while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) {
1830                     XmlNode xmlNode = Document.ReadNode(r);
1831                     xmlNodeList.Add(xmlNode);
1832                     if (unknownElement != null) unknownElement.AppendChild(xmlNode);
1833                     Reader.MoveToContent();
1834                     CheckReaderCount(ref whileIterations, ref readerCount);
1835                 }
1836                 ReadEndElement();
1837
1838             }
1839
1840
1841             if(xmlNodeList.Count <= skippableNodeCount)
1842                 return new object();
1843
1844             XmlNode[] childNodes =  (XmlNode[])xmlNodeList.ToArray(typeof(XmlNode));
1845
1846             UnknownNode(unknownNode, null, null);
1847             return childNodes;
1848         }
1849
1850         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReader.CheckReaderCount"]/*' />
1851         protected void CheckReaderCount(ref int whileIterations, ref int readerCount)
1852         {
1853             if (checkDeserializeAdvances)
1854             {
1855                 whileIterations++;
1856                 if ((whileIterations & 0x80) == 0x80)
1857                 {
1858                     if (readerCount == ReaderCount)
1859                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorReaderAdvance));
1860                     readerCount = ReaderCount;
1861                 }
1862             }
1863         }
1864
1865         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup"]/*' />
1866         ///<internalonly/>
1867         protected class Fixup {
1868             XmlSerializationFixupCallback callback;
1869             object source;
1870             string[] ids;
1871
1872             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup.Fixup1"]/*' />
1873             public Fixup(object o, XmlSerializationFixupCallback callback, int count) 
1874                 : this (o, callback, new string[count]) {
1875             }
1876
1877             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup.Fixup2"]/*' />
1878             public Fixup(object o, XmlSerializationFixupCallback callback, string[] ids) {
1879                 this.callback = callback;
1880                 this.Source = o;
1881                 this.ids = ids;
1882             }
1883
1884             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup.Callback"]/*' />
1885             public XmlSerializationFixupCallback Callback {
1886                 get { return callback; }
1887             }
1888
1889             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup.Source"]/*' />
1890             public object Source {
1891                 get { return source; }
1892                 set { source = value; }
1893             }
1894
1895             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="Fixup.Ids"]/*' />
1896             public string[] Ids {
1897                 get { return ids; }
1898             }
1899         }
1900
1901         /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="CollectionFixup"]/*' />
1902         protected class CollectionFixup {
1903             XmlSerializationCollectionFixupCallback callback;
1904             object collection;
1905             object collectionItems;
1906
1907             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="CollectionFixup.CollectionFixup"]/*' />
1908             public CollectionFixup(object collection, XmlSerializationCollectionFixupCallback callback, object collectionItems) {
1909                 this.callback = callback;
1910                 this.collection = collection;
1911                 this.collectionItems = collectionItems;
1912             }
1913
1914             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="CollectionFixup.Callback"]/*' />
1915             public XmlSerializationCollectionFixupCallback Callback {
1916                 get { return callback; }
1917             }
1918
1919             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="CollectionFixup.Collection"]/*' />
1920             public object Collection {
1921                 get { return collection; }
1922             }
1923
1924             /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="CollectionFixup.CollectionItems"]/*' />
1925             public object CollectionItems {
1926                 get { return collectionItems; }
1927             }
1928         }
1929     }
1930
1931     /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationFixupCallback"]/*' />
1932     ///<internalonly/>
1933     public delegate void XmlSerializationFixupCallback(object fixup);
1934
1935
1936     /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationCollectionFixupCallback"]/*' />
1937     ///<internalonly/>
1938     public delegate void XmlSerializationCollectionFixupCallback(object collection, object collectionItems);
1939
1940     /// <include file='doc\XmlSerializationReader.uex' path='docs/doc[@for="XmlSerializationReadCallback"]/*' />
1941     ///<internalonly/>
1942     public delegate object XmlSerializationReadCallback();
1943
1944     internal class XmlSerializationReaderCodeGen : XmlSerializationCodeGen {
1945         Hashtable idNames = new Hashtable();
1946         Hashtable enums;
1947         Hashtable createMethods = new Hashtable();
1948         int nextCreateMethodNumber = 0;
1949         int nextIdNumber = 0;
1950         int nextWhileLoopIndex = 0;
1951
1952         internal Hashtable Enums {
1953             get {
1954                 if (enums == null) {
1955                     enums = new Hashtable();
1956                 }
1957                 return enums;
1958             }
1959         }
1960
1961         class CreateCollectionInfo {
1962             string name;
1963             TypeDesc td;
1964
1965             internal CreateCollectionInfo(string name, TypeDesc td) {
1966                 this.name = name;
1967                 this.td = td;
1968             }
1969             internal string Name {
1970                 get { return name; }
1971             }
1972
1973             internal TypeDesc TypeDesc {
1974                 get { return td; }
1975             }
1976         }
1977         class Member {
1978             string source;
1979             string arrayName;
1980             string arraySource;
1981             string choiceArrayName;
1982             string choiceSource;
1983             string choiceArraySource;
1984             MemberMapping mapping;
1985             bool isArray;
1986             bool isList;
1987             bool isNullable;
1988             bool multiRef;
1989             int fixupIndex = -1;
1990             string paramsReadSource;
1991             string checkSpecifiedSource;
1992
1993             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arrayName, int i, MemberMapping mapping) 
1994                 : this(outerClass, source, null, arrayName, i, mapping, false, null) {
1995             }
1996             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arrayName, int i, MemberMapping mapping, string choiceSource)
1997                 : this(outerClass, source, null, arrayName, i, mapping, false, choiceSource) {
1998             }
1999             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping) 
2000                 : this (outerClass, source, arraySource, arrayName, i, mapping, false, null) { 
2001             }
2002             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping, string choiceSource) 
2003                 : this (outerClass, source, arraySource, arrayName, i, mapping, false, choiceSource) { 
2004             }
2005             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arrayName, int i, MemberMapping mapping, bool multiRef)
2006                 : this(outerClass, source, null, arrayName, i, mapping, multiRef, null) {
2007             }
2008             internal Member(XmlSerializationReaderCodeGen outerClass, string source, string arraySource, string arrayName, int i, MemberMapping mapping, bool multiRef, string choiceSource) {
2009                 this.source = source;
2010                 this.arrayName = arrayName + "_" + i.ToString(CultureInfo.InvariantCulture);
2011                 this.choiceArrayName = "choice_" + this.arrayName;
2012                 this.choiceSource = choiceSource;
2013                 ElementAccessor[] elements = mapping.Elements;
2014
2015                 if (mapping.TypeDesc.IsArrayLike) {
2016                     if (arraySource != null)
2017                         this.arraySource = arraySource;
2018                     else
2019                         this.arraySource = outerClass.GetArraySource(mapping.TypeDesc, this.arrayName, multiRef);
2020                     isArray = mapping.TypeDesc.IsArray;
2021                     isList = !isArray;
2022                     if (mapping.ChoiceIdentifier != null) {
2023                         this.choiceArraySource = outerClass.GetArraySource(mapping.TypeDesc, this.choiceArrayName, multiRef);
2024
2025                         string a = choiceArrayName;
2026                         string c = "c" + a;
2027                         bool choiceUseReflection = mapping.ChoiceIdentifier.Mapping.TypeDesc.UseReflection;
2028                         string choiceTypeFullName = mapping.ChoiceIdentifier.Mapping.TypeDesc.CSharpName;
2029                         string castString = choiceUseReflection?"":"(" + choiceTypeFullName + "[])";
2030                         
2031                         string init = a + " = " + castString +
2032                             "EnsureArrayIndex(" + a + ", " + c + ", " + outerClass.RaCodeGen.GetStringForTypeof(choiceTypeFullName, choiceUseReflection) + ");";
2033                         this.choiceArraySource = init + outerClass.RaCodeGen.GetStringForArrayMember(a,  c + "++", mapping.ChoiceIdentifier.Mapping.TypeDesc);
2034                     }
2035                     else {
2036                         this.choiceArraySource = this.choiceSource;
2037                     }
2038                 }
2039                 else {
2040                     this.arraySource = arraySource == null ? source : arraySource;
2041                     this.choiceArraySource = this.choiceSource;
2042                 }
2043                 this.mapping = mapping;
2044             }
2045
2046             internal MemberMapping Mapping {
2047                 get { return mapping; }
2048             }
2049
2050             internal string Source {
2051                 get { return source; }
2052             }
2053
2054             internal string ArrayName {
2055                 get { return arrayName; }
2056             }
2057
2058             internal string ArraySource {
2059                 get { return arraySource; }
2060             }
2061
2062             internal bool IsList {
2063                 get { return isList; }
2064             }
2065
2066             internal bool IsArrayLike {
2067                 get { return (isArray || isList); }
2068             }
2069
2070             internal bool IsNullable {
2071                 get { return isNullable; }
2072                 set { isNullable = value; }
2073             }
2074
2075             internal bool MultiRef {
2076                 get { return multiRef; }
2077                 set { multiRef = value; }
2078             }
2079
2080             internal int FixupIndex {
2081                 get { return fixupIndex; }
2082                 set { fixupIndex = value; }
2083             }
2084
2085             internal string ParamsReadSource {
2086                 get { return paramsReadSource; }
2087                 set { paramsReadSource = value; }
2088             }
2089             
2090             internal string CheckSpecifiedSource {
2091                 get { return checkSpecifiedSource; }
2092                 set { checkSpecifiedSource = value; }
2093             }
2094
2095             internal string ChoiceSource {
2096                 get { return choiceSource; }
2097             }
2098             internal string ChoiceArrayName {
2099                 get { return choiceArrayName; }
2100             }
2101             internal string ChoiceArraySource {
2102                 get { return choiceArraySource; }
2103             }
2104         }
2105
2106         internal XmlSerializationReaderCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className) : base(writer, scopes, access, className) {
2107         }
2108
2109         internal void GenerateBegin() {
2110             Writer.Write(Access);
2111             Writer.Write(" class ");
2112             Writer.Write(ClassName);
2113             Writer.Write(" : ");
2114             Writer.Write(typeof(XmlSerializationReader).FullName);
2115             Writer.WriteLine(" {");
2116             Writer.Indent++;
2117             foreach (TypeScope scope in Scopes) {
2118                 foreach (TypeMapping mapping in scope.TypeMappings) {
2119                     if (mapping is StructMapping || mapping is EnumMapping || mapping is NullableMapping) 
2120                         MethodNames.Add(mapping, NextMethodName(mapping.TypeDesc.Name));
2121                 }
2122                 RaCodeGen.WriteReflectionInit(scope);
2123             }
2124             // pre-generate read methods only for the encoded soap
2125             foreach (TypeScope scope in Scopes) {
2126                 foreach (TypeMapping mapping in scope.TypeMappings) {
2127                     if (!mapping.IsSoap)
2128                         continue;
2129                     if (mapping is StructMapping)
2130                         WriteStructMethod((StructMapping)mapping);
2131                     else if (mapping is EnumMapping)
2132                         WriteEnumMethod((EnumMapping)mapping);
2133                     else if (mapping is NullableMapping) {
2134                         WriteNullableMethod((NullableMapping)mapping);
2135                     }
2136                 }
2137             }
2138         }
2139
2140         internal override void GenerateMethod(TypeMapping mapping) {
2141             if (GeneratedMethods.Contains(mapping))
2142                 return;
2143
2144             GeneratedMethods[mapping] = mapping;
2145             if (mapping is StructMapping) {
2146                 WriteStructMethod((StructMapping)mapping);
2147             }
2148             else if (mapping is EnumMapping) {
2149                 WriteEnumMethod((EnumMapping)mapping);
2150             }
2151             else if (mapping is NullableMapping) {
2152                 WriteNullableMethod((NullableMapping)mapping);
2153             }
2154         }
2155
2156         internal void GenerateEnd() {
2157             GenerateEnd(new string[0], new XmlMapping[0], new Type[0]);
2158         }
2159         internal void GenerateEnd(string[] methods, XmlMapping[] xmlMappings, Type[] types) {
2160             GenerateReferencedMethods();
2161             GenerateInitCallbacksMethod();
2162
2163             foreach (CreateCollectionInfo c in createMethods.Values) {
2164                 WriteCreateCollectionMethod(c);
2165             }
2166
2167             Writer.WriteLine();
2168             foreach (string idName in idNames.Values) {
2169                 Writer.Write("string ");
2170                 Writer.Write(idName);
2171                 Writer.WriteLine(";");
2172             }                
2173
2174             Writer.WriteLine();
2175             Writer.WriteLine("protected override void InitIDs() {");
2176             Writer.Indent++;
2177             foreach (string id in idNames.Keys) {
2178                 // 
2179                 string idName = (string)idNames[id];
2180                 Writer.Write(idName);
2181                 Writer.Write(" = Reader.NameTable.Add(");
2182                 WriteQuotedCSharpString(id);
2183                 Writer.WriteLine(");");
2184             }
2185             Writer.Indent--;
2186             Writer.WriteLine("}");
2187
2188             Writer.Indent--;
2189             Writer.WriteLine("}");
2190         }
2191
2192         internal string GenerateElement(XmlMapping xmlMapping) {
2193             if (!xmlMapping.IsReadable)
2194                 return null;
2195             if (!xmlMapping.GenerateSerializer) 
2196                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
2197             if (xmlMapping is XmlTypeMapping)
2198                 return GenerateTypeElement((XmlTypeMapping)xmlMapping);
2199             else if (xmlMapping is XmlMembersMapping)
2200                 return GenerateMembersElement((XmlMembersMapping)xmlMapping);
2201             else
2202                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping");
2203         }
2204
2205         void WriteIsStartTag(string name, string ns) {
2206             Writer.Write("if (Reader.IsStartElement(");
2207             WriteID(name);
2208             Writer.Write(", ");
2209             WriteID(ns);
2210             Writer.WriteLine(")) {");
2211             Writer.Indent++;
2212         }
2213
2214         void WriteUnknownNode(string func, string node, ElementAccessor e, bool anyIfs) {
2215             if (anyIfs) {
2216                 Writer.WriteLine("else {");
2217                 Writer.Indent++;
2218             }
2219             Writer.Write(func);
2220             Writer.Write("(");
2221             Writer.Write(node);
2222             if (e != null) {
2223                 Writer.Write(", ");
2224                 string expectedElement = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
2225                 expectedElement += ":";
2226                 expectedElement += e.Name;
2227                 ReflectionAwareCodeGen.WriteQuotedCSharpString(Writer, expectedElement);
2228             }
2229             Writer.WriteLine(");");
2230             if (anyIfs) {
2231                 Writer.Indent--;
2232                 Writer.WriteLine("}");
2233             }
2234         }
2235
2236         void GenerateInitCallbacksMethod() {
2237             Writer.WriteLine();
2238             Writer.WriteLine("protected override void InitCallbacks() {");
2239             Writer.Indent++;
2240
2241             string dummyArrayMethodName = NextMethodName("Array");
2242             bool needDummyArrayMethod = false;
2243             foreach (TypeScope scope in Scopes) {
2244                 foreach (TypeMapping mapping in scope.TypeMappings) {
2245                     if (mapping.IsSoap && 
2246                         (mapping is StructMapping || mapping is EnumMapping || mapping is ArrayMapping || mapping is NullableMapping) &&
2247                         !mapping.TypeDesc.IsRoot) {
2248
2249                         string methodName;
2250                         if (mapping is ArrayMapping) {
2251                             methodName = dummyArrayMethodName;
2252                             needDummyArrayMethod = true;
2253                         }
2254                         else
2255                             methodName = (string)MethodNames[mapping];
2256
2257                         Writer.Write("AddReadCallback(");
2258                         WriteID(mapping.TypeName);
2259                         Writer.Write(", ");
2260                         WriteID(mapping.Namespace);
2261                         Writer.Write(", ");
2262                         Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName,mapping.TypeDesc.UseReflection));
2263                         Writer.Write(", new ");
2264                         Writer.Write(typeof(XmlSerializationReadCallback).FullName);
2265                         Writer.Write("(this.");
2266                         Writer.Write(methodName);
2267                         Writer.WriteLine("));");
2268                     }
2269                 }
2270             }
2271
2272             Writer.Indent--;
2273             Writer.WriteLine("}");
2274
2275             if (needDummyArrayMethod) {
2276                 Writer.WriteLine();
2277                 Writer.Write("object ");
2278                 Writer.Write(dummyArrayMethodName);
2279                 Writer.WriteLine("() {");
2280                 Writer.Indent++;
2281                 Writer.WriteLine("// dummy array method");
2282                 Writer.WriteLine("UnknownNode(null);");
2283                 Writer.WriteLine("return null;");
2284                 Writer.Indent--;
2285                 Writer.WriteLine("}");
2286             }
2287         }
2288
2289        
2290         string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) {
2291             if (xmlMembersMapping.Accessor.IsSoap)
2292                 return GenerateEncodedMembersElement(xmlMembersMapping);
2293             else
2294                 return GenerateLiteralMembersElement(xmlMembersMapping);
2295         }
2296
2297         string GetChoiceIdentifierSource(MemberMapping[] mappings, MemberMapping member) {
2298             string choiceSource = null;
2299             if (member.ChoiceIdentifier != null) {
2300                 for (int j = 0; j < mappings.Length; j++) {
2301                     if (mappings[j].Name == member.ChoiceIdentifier.MemberName) {
2302                         choiceSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
2303                         break;
2304                     }
2305                 }
2306                 #if DEBUG
2307                     // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
2308                     if (choiceSource == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Can not find " + member.ChoiceIdentifier.MemberName + " in the members mapping."));
2309                 #endif
2310
2311             }
2312             return choiceSource;
2313         }
2314
2315         string GetChoiceIdentifierSource(MemberMapping mapping, string parent, TypeDesc parentTypeDesc) {
2316             if (mapping.ChoiceIdentifier == null) return "";
2317             CodeIdentifier.CheckValidIdentifier(mapping.ChoiceIdentifier.MemberName);
2318             return RaCodeGen.GetStringForMember(parent,  mapping.ChoiceIdentifier.MemberName, parentTypeDesc);
2319         }
2320
2321         string GenerateLiteralMembersElement(XmlMembersMapping xmlMembersMapping) {
2322             ElementAccessor element = xmlMembersMapping.Accessor;
2323             MemberMapping[] mappings = ((MembersMapping)element.Mapping).Members;
2324             bool hasWrapperElement = ((MembersMapping)element.Mapping).HasWrapperElement;
2325             string methodName = NextMethodName(element.Name);
2326             Writer.WriteLine();
2327             Writer.Write("public object[] ");
2328             Writer.Write(methodName);
2329             Writer.WriteLine("() {");
2330             Writer.Indent++;
2331             Writer.WriteLine("Reader.MoveToContent();");
2332
2333             Writer.Write("object[] p = new object[");
2334             Writer.Write(mappings.Length.ToString(CultureInfo.InvariantCulture));
2335             Writer.WriteLine("];");
2336             InitializeValueTypes("p", mappings);
2337
2338             int wrapperLoopIndex = 0;
2339             if (hasWrapperElement) {
2340                 wrapperLoopIndex = WriteWhileNotLoopStart();
2341                 Writer.Indent++;
2342                 WriteIsStartTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
2343             }
2344
2345             Member anyText = null;
2346             Member anyElement = null;
2347             Member anyAttribute = null; 
2348
2349             ArrayList membersList = new ArrayList();
2350             ArrayList textOrArrayMembersList = new ArrayList();
2351             ArrayList attributeMembersList = new ArrayList();
2352             
2353             for (int i = 0; i < mappings.Length; i++) {
2354                 MemberMapping mapping = mappings[i];
2355                 string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
2356                 string arraySource = source;
2357                 if (mapping.Xmlns != null) {
2358                     arraySource = "((" + mapping.TypeDesc.CSharpName + ")" + source + ")";
2359                 }
2360                 string choiceSource = GetChoiceIdentifierSource(mappings, mapping);
2361                 Member member = new Member(this, source, arraySource, "a", i, mapping, choiceSource);
2362                 Member anyMember = new Member(this, source, null, "a", i, mapping, choiceSource);
2363                 if (!mapping.IsSequence)
2364                     member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
2365                 if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite) {
2366                     string nameSpecified = mapping.Name + "Specified";
2367                     for (int j = 0; j < mappings.Length; j++) {
2368                         if (mappings[j].Name == nameSpecified) {
2369                             member.CheckSpecifiedSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
2370                             break;
2371                         }
2372                     }
2373                 }
2374                 bool foundAnyElement = false;
2375                 if (mapping.Text != null) anyText = anyMember;
2376                 if (mapping.Attribute != null && mapping.Attribute.Any)
2377                     anyAttribute = anyMember;
2378                 if (mapping.Attribute != null || mapping.Xmlns != null)
2379                     attributeMembersList.Add(member);
2380                 else if (mapping.Text != null)
2381                     textOrArrayMembersList.Add(member);
2382
2383                 if (!mapping.IsSequence) {
2384                     for (int j = 0; j < mapping.Elements.Length; j++) {
2385                         if (mapping.Elements[j].Any && mapping.Elements[j].Name.Length == 0) {
2386                             anyElement = anyMember;
2387                             if (mapping.Attribute == null && mapping.Text == null)
2388                                 textOrArrayMembersList.Add(anyMember);
2389                             foundAnyElement = true;
2390                             break;
2391                         }
2392                     }
2393                 }
2394                 if (mapping.Attribute != null || mapping.Text != null || foundAnyElement)
2395                     membersList.Add(anyMember);
2396                 else if (mapping.TypeDesc.IsArrayLike && !(mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping)) {
2397                     membersList.Add(anyMember);
2398                     textOrArrayMembersList.Add(anyMember);
2399                 }
2400                 else {
2401                     if (mapping.TypeDesc.IsArrayLike && !mapping.TypeDesc.IsArray)
2402                         member.ParamsReadSource = null; // collection
2403                     membersList.Add(member);
2404                 }
2405             }
2406             Member[] members = (Member[]) membersList.ToArray(typeof(Member));
2407             Member[] textOrArrayMembers = (Member[]) textOrArrayMembersList.ToArray(typeof(Member));
2408
2409             if (members.Length > 0 && members[0].Mapping.IsReturnValue) Writer.WriteLine("IsReturnValue = true;");
2410             
2411             WriteParamsRead(mappings.Length);
2412
2413             if (attributeMembersList.Count > 0) {
2414                 Member[] attributeMembers = (Member[]) attributeMembersList.ToArray(typeof(Member));
2415                 WriteMemberBegin(attributeMembers);
2416                 WriteAttributes(attributeMembers, anyAttribute, "UnknownNode", "(object)p");
2417                 WriteMemberEnd(attributeMembers);
2418                 Writer.WriteLine("Reader.MoveToElement();");
2419             }
2420
2421             WriteMemberBegin(textOrArrayMembers);
2422
2423             if (hasWrapperElement) {
2424                 Writer.WriteLine("if (Reader.IsEmptyElement) { Reader.Skip(); Reader.MoveToContent(); continue; }");
2425                 Writer.WriteLine("Reader.ReadStartElement();");
2426             }
2427             if (IsSequence(members)) {
2428                 Writer.WriteLine("int state = 0;");
2429             }
2430             int loopIndex = WriteWhileNotLoopStart();
2431             Writer.Indent++;
2432
2433             string unknownNode = "UnknownNode((object)p, " + ExpectedElements(members) + ");";
2434             WriteMemberElements(members, unknownNode, unknownNode, anyElement, anyText, null);
2435
2436             Writer.WriteLine("Reader.MoveToContent();");
2437             WriteWhileLoopEnd(loopIndex);
2438
2439             WriteMemberEnd(textOrArrayMembers);
2440
2441             if (hasWrapperElement) {
2442                 Writer.WriteLine("ReadEndElement();");
2443
2444                 Writer.Indent--;
2445                 Writer.WriteLine("}");
2446
2447                 WriteUnknownNode("UnknownNode", "null", element, true);
2448
2449                 Writer.WriteLine("Reader.MoveToContent();");
2450                 WriteWhileLoopEnd(wrapperLoopIndex);
2451             }
2452             
2453             Writer.WriteLine("return p;");
2454             Writer.Indent--;
2455             Writer.WriteLine("}");
2456             
2457             return methodName;
2458         }
2459         
2460         void InitializeValueTypes(string arrayName, MemberMapping[] mappings) {
2461             for (int i = 0; i < mappings.Length; i++) {
2462                 if (!mappings[i].TypeDesc.IsValueType)
2463                     continue;
2464                 Writer.Write(arrayName);
2465                 Writer.Write("[");
2466                 Writer.Write(i.ToString(CultureInfo.InvariantCulture));
2467                 Writer.Write("] = ");
2468
2469                 if (mappings[i].TypeDesc.IsOptionalValue && mappings[i].TypeDesc.BaseTypeDesc.UseReflection) {
2470                     Writer.Write("null");
2471                 }
2472                 else {
2473                     Writer.Write(RaCodeGen.GetStringForCreateInstance(mappings[i].TypeDesc.CSharpName, mappings[i].TypeDesc.UseReflection, false, false));
2474                 }
2475                 Writer.WriteLine(";");
2476             }
2477         }
2478         
2479         string GenerateEncodedMembersElement(XmlMembersMapping xmlMembersMapping) {
2480             ElementAccessor element = xmlMembersMapping.Accessor;
2481             MembersMapping membersMapping = (MembersMapping)element.Mapping;
2482             MemberMapping[] mappings = membersMapping.Members;
2483             bool hasWrapperElement = membersMapping.HasWrapperElement;
2484             bool writeAccessors = membersMapping.WriteAccessors;
2485             string methodName = NextMethodName(element.Name);
2486             Writer.WriteLine();
2487             Writer.Write("public object[] ");
2488             Writer.Write(methodName);
2489             Writer.WriteLine("() {");
2490             Writer.Indent++;
2491
2492             Writer.WriteLine("Reader.MoveToContent();");
2493
2494             Writer.Write("object[] p = new object[");
2495             Writer.Write(mappings.Length.ToString(CultureInfo.InvariantCulture));
2496             Writer.WriteLine("];");
2497             InitializeValueTypes("p", mappings);
2498
2499             if (hasWrapperElement) {
2500                 WriteReadNonRoots();
2501
2502                 if (membersMapping.ValidateRpcWrapperElement) {
2503                     Writer.Write("if (!");
2504                     WriteXmlNodeEqual("Reader", element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
2505                     Writer.WriteLine(") throw CreateUnknownNodeException();");
2506                 }
2507                 Writer.WriteLine("bool isEmptyWrapper = Reader.IsEmptyElement;");
2508                 Writer.WriteLine("Reader.ReadStartElement();");
2509             }
2510
2511             Member[] members = new Member[mappings.Length];
2512             for (int i = 0; i < mappings.Length; i++) {
2513                 MemberMapping mapping = mappings[i];
2514                 string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
2515                 string arraySource = source;
2516                 if (mapping.Xmlns != null) {
2517                     arraySource = "((" + mapping.TypeDesc.CSharpName + ")" + source + ")";
2518                 }
2519                 Member member = new Member(this,source, arraySource, "a", i, mapping);
2520                 if (!mapping.IsSequence)
2521                     member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
2522                 members[i] = member;
2523
2524                 if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite) {
2525                     string nameSpecified = mapping.Name + "Specified";
2526                     for (int j = 0; j < mappings.Length; j++) {
2527                         if (mappings[j].Name == nameSpecified) {
2528                             member.CheckSpecifiedSource = "p[" + j.ToString(CultureInfo.InvariantCulture) + "]";
2529                             break;
2530                         }
2531                     }
2532                 }
2533
2534             }
2535
2536             string fixupMethodName = "fixup_" + methodName;
2537             bool anyFixups = WriteMemberFixupBegin(members, fixupMethodName, "p");
2538
2539             if (members.Length > 0 && members[0].Mapping.IsReturnValue) Writer.WriteLine("IsReturnValue = true;");
2540
2541             string checkTypeHrefSource = (!hasWrapperElement && !writeAccessors) ? "hrefList" : null;
2542             if (checkTypeHrefSource != null)
2543                 WriteInitCheckTypeHrefList(checkTypeHrefSource);
2544                      
2545             WriteParamsRead(mappings.Length);
2546             int loopIndex = WriteWhileNotLoopStart();
2547             Writer.Indent++;
2548
2549             string unrecognizedElementSource = checkTypeHrefSource == null ? "UnknownNode((object)p);" : "if (Reader.GetAttribute(\"id\", null) != null) { ReadReferencedElement(); } else { UnknownNode((object)p); }";
2550             WriteMemberElements(members, unrecognizedElementSource, "UnknownNode((object)p);", null, null, checkTypeHrefSource);
2551             Writer.WriteLine("Reader.MoveToContent();");
2552
2553             WriteWhileLoopEnd(loopIndex);
2554
2555             if (hasWrapperElement)
2556                 Writer.WriteLine("if (!isEmptyWrapper) ReadEndElement();");
2557
2558             if (checkTypeHrefSource != null)
2559                 WriteHandleHrefList(members, checkTypeHrefSource);
2560
2561             Writer.WriteLine("ReadReferencedElements();");
2562             Writer.WriteLine("return p;");
2563
2564             Writer.Indent--;
2565             Writer.WriteLine("}");
2566
2567             if (anyFixups) WriteFixupMethod(fixupMethodName, members, "object[]", false, false, "p");
2568           
2569             return methodName;
2570         }
2571
2572         void WriteCreateCollection(TypeDesc td, string source) {
2573             bool useReflection = td.UseReflection;
2574             string item = (td.ArrayElementTypeDesc == null ? "object" : td.ArrayElementTypeDesc.CSharpName) + "[]";
2575             bool arrayElementUseReflection = td.ArrayElementTypeDesc == null?false:td.ArrayElementTypeDesc.UseReflection;
2576             
2577             //cannot call WriteArrayLocalDecl since 'ci' is always
2578             //array and 'td' corresponds to 'c'
2579             if (arrayElementUseReflection)
2580                 item = typeof(Array).FullName;
2581             Writer.Write(item);
2582             Writer.Write(" ");
2583             Writer.Write("ci =");
2584             Writer.Write("("+item+")");
2585             Writer.Write(source);
2586             Writer.WriteLine(";");
2587
2588             Writer.WriteLine("for (int i = 0; i < ci.Length; i++) {");
2589             Writer.Indent++;
2590             Writer.Write(RaCodeGen.GetStringForMethod("c", td.CSharpName,"Add",useReflection));
2591             
2592             //cannot call GetStringForArrayMember since 'ci' is always
2593             //array and 'td' corresponds to 'c'
2594             if (!arrayElementUseReflection)
2595                 Writer.Write( "ci[i]");
2596             else 
2597                 Writer.Write(RaCodeGen.GetReflectionVariable(typeof(Array).FullName, "0") + "[ci , i]");
2598
2599             
2600             if (useReflection) Writer.WriteLine("}");
2601             Writer.WriteLine(");");
2602             Writer.Indent--;
2603             Writer.WriteLine("}");
2604         }
2605
2606         string GenerateTypeElement(XmlTypeMapping xmlTypeMapping) {
2607             ElementAccessor element = xmlTypeMapping.Accessor;
2608             TypeMapping mapping = element.Mapping;
2609             string methodName = NextMethodName(element.Name);
2610             Writer.WriteLine();
2611             Writer.Write("public object ");
2612             Writer.Write(methodName);
2613             Writer.WriteLine("() {");
2614             Writer.Indent++;
2615             Writer.WriteLine("object o = null;");
2616             MemberMapping member = new MemberMapping();
2617             member.TypeDesc = mapping.TypeDesc;
2618             //member.ReadOnly = !mapping.TypeDesc.HasDefaultConstructor;
2619             member.Elements = new ElementAccessor[] { element };
2620             Member[] members = new Member[] { new Member(this,"o", "o", "a", 0, member) };
2621             Writer.WriteLine("Reader.MoveToContent();");
2622             string unknownNode = "UnknownNode(null, " + ExpectedElements(members) + ");";
2623             WriteMemberElements(members, "throw CreateUnknownNodeException();", unknownNode, element.Any ? members[0] : null,  null, null);
2624             if (element.IsSoap) {
2625                 Writer.WriteLine("Referenced(o);");
2626                 Writer.WriteLine("ReadReferencedElements();");
2627             }
2628             Writer.WriteLine("return (object)o;");
2629             Writer.Indent--;
2630             Writer.WriteLine("}");
2631             return methodName;
2632         }
2633         
2634         string NextMethodName(string name) {
2635             return "Read" + (++NextMethodNumber).ToString(CultureInfo.InvariantCulture) + "_" + CodeIdentifier.MakeValidInternal(name);
2636         }
2637         
2638         string NextIdName(string name) {
2639             return "id" + (++nextIdNumber).ToString(CultureInfo.InvariantCulture) + "_" + CodeIdentifier.MakeValidInternal(name);
2640         }
2641
2642         void WritePrimitive(TypeMapping mapping, string source) {
2643             if (mapping is EnumMapping) {
2644                 string enumMethodName = ReferenceMapping(mapping);
2645                 if (enumMethodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlMissingMethodEnum, mapping.TypeDesc.Name));
2646                 if (mapping.IsSoap) {
2647                     // SOAP methods are not strongly-typed (the return object), so we need to add a cast
2648                     Writer.Write("(");
2649                     Writer.Write(mapping.TypeDesc.CSharpName);
2650                     Writer.Write(")");
2651                 }
2652                 Writer.Write(enumMethodName);
2653                 Writer.Write("(");
2654                 if (!mapping.IsSoap) Writer.Write(source);
2655                 Writer.Write(")");
2656             }
2657             else if (mapping.TypeDesc == StringTypeDesc) {
2658                 Writer.Write(source);
2659             }
2660             else if (mapping.TypeDesc.FormatterName == "String") {
2661                 if (mapping.TypeDesc.CollapseWhitespace) {
2662                     Writer.Write("CollapseWhitespace(");
2663                     Writer.Write(source);
2664                     Writer.Write(")");
2665                 }
2666                 else {
2667                     Writer.Write(source);
2668                 }
2669             }
2670             else {
2671                 if (!mapping.TypeDesc.HasCustomFormatter) {
2672                     Writer.Write(typeof(XmlConvert).FullName);
2673                     Writer.Write(".");
2674                 }
2675                 Writer.Write("To");
2676                 Writer.Write(mapping.TypeDesc.FormatterName);
2677                 Writer.Write("(");
2678                 Writer.Write(source);
2679                 Writer.Write(")");
2680             }
2681         }
2682
2683         string MakeUnique(EnumMapping mapping, string name) {
2684             string uniqueName = name;
2685             object m = Enums[uniqueName];
2686             if (m != null) {
2687                 if (m == mapping) {
2688                     // we already have created the hashtable
2689                     return null;
2690                 }
2691                 int i = 0;
2692                 while (m != null) {
2693                     i++;
2694                     uniqueName = name + i.ToString(CultureInfo.InvariantCulture);
2695                     m = Enums[uniqueName];
2696                 }
2697             }
2698             Enums.Add(uniqueName, mapping);
2699             return uniqueName;
2700         }
2701
2702         string WriteHashtable(EnumMapping mapping, string typeName) {
2703
2704             CodeIdentifier.CheckValidIdentifier(typeName);
2705             string propName = MakeUnique(mapping, typeName + "Values");
2706             if (propName == null) return CodeIdentifier.GetCSharpName(typeName);
2707             string memberName = MakeUnique(mapping, "_" + propName);
2708             propName = CodeIdentifier.GetCSharpName(propName);
2709
2710             Writer.WriteLine();
2711             Writer.Write(typeof(Hashtable).FullName);
2712             Writer.Write(" ");
2713             Writer.Write(memberName);
2714             Writer.WriteLine(";");
2715             Writer.WriteLine();
2716
2717             Writer.Write("internal ");
2718             Writer.Write(typeof(Hashtable).FullName);
2719             Writer.Write(" ");
2720             Writer.Write(propName);
2721             Writer.WriteLine(" {");
2722             Writer.Indent++;
2723
2724             Writer.WriteLine("get {");
2725             Writer.Indent++;
2726
2727             Writer.Write("if ((object)");
2728             Writer.Write(memberName);
2729             Writer.WriteLine(" == null) {");
2730             Writer.Indent++;
2731
2732             Writer.Write(typeof(Hashtable).FullName);
2733             Writer.Write(" h = new ");
2734             Writer.Write(typeof(Hashtable).FullName);
2735             Writer.WriteLine("();");
2736
2737             ConstantMapping[] constants = mapping.Constants;
2738
2739             for (int i = 0; i < constants.Length; i++) {
2740                 Writer.Write("h.Add(");
2741                 WriteQuotedCSharpString(constants[i].XmlName);
2742                 if (!mapping.TypeDesc.UseReflection){
2743                     Writer.Write(", (long)");
2744                     Writer.Write(mapping.TypeDesc.CSharpName);
2745                     Writer.Write(".@");
2746                     CodeIdentifier.CheckValidIdentifier(constants[i].Name);
2747                     Writer.Write(constants[i].Name);
2748                 }
2749                 else{
2750                     Writer.Write(", ");
2751                     Writer.Write(constants[i].Value.ToString(CultureInfo.InvariantCulture)+"L");
2752                 }
2753
2754                 Writer.WriteLine(");");
2755             }
2756
2757             Writer.Write(memberName);
2758             Writer.WriteLine(" = h;");
2759
2760             Writer.Indent--;
2761             Writer.WriteLine("}");
2762
2763             Writer.Write("return ");
2764             Writer.Write(memberName);
2765             Writer.WriteLine(";");
2766
2767             Writer.Indent--;
2768             Writer.WriteLine("}");
2769
2770             Writer.Indent--;
2771             Writer.WriteLine("}");
2772
2773             return propName;
2774         }
2775
2776         void WriteEnumMethod(EnumMapping mapping) {
2777             string tableName = null;
2778             if (mapping.IsFlags)
2779                 tableName = WriteHashtable(mapping, mapping.TypeDesc.Name);
2780
2781             string methodName = (string)MethodNames[mapping];
2782             Writer.WriteLine();
2783             bool useReflection = mapping.TypeDesc.UseReflection;
2784             string fullTypeName = mapping.TypeDesc.CSharpName;
2785
2786             if (mapping.IsSoap) {
2787                 Writer.Write("object");
2788                 Writer.Write(" ");
2789                 Writer.Write(methodName);
2790                 Writer.WriteLine("() {");
2791                 Writer.Indent++;
2792                 Writer.WriteLine("string s = Reader.ReadElementString();");
2793             }
2794             else {
2795                 Writer.Write(useReflection?"object":fullTypeName);
2796                 Writer.Write(" ");
2797                 Writer.Write(methodName);
2798                 Writer.WriteLine("(string s) {");
2799                 Writer.Indent++;
2800             }
2801
2802             ConstantMapping[] constants = mapping.Constants;
2803             if (mapping.IsFlags) {
2804                 if (useReflection){
2805                     Writer.Write("return ");
2806                     Writer.Write(typeof(Enum).FullName);
2807                     Writer.Write(".ToObject(");
2808                     Writer.Write(RaCodeGen.GetStringForTypeof(fullTypeName, useReflection));
2809                     Writer.Write(", ToEnum(s, ");
2810                     Writer.Write(tableName);
2811                     Writer.Write(", ");
2812                     WriteQuotedCSharpString(fullTypeName);
2813                     Writer.WriteLine("));");
2814                 }
2815                 else{
2816                     Writer.Write("return (");
2817                     Writer.Write(fullTypeName);
2818                     Writer.Write(")ToEnum(s, ");
2819                     Writer.Write(tableName);
2820                     Writer.Write(", ");
2821                     WriteQuotedCSharpString(fullTypeName);
2822                     Writer.WriteLine(");");
2823                 }
2824             }
2825             else {
2826                 Writer.WriteLine("switch (s) {");
2827                 Writer.Indent++;
2828                 Hashtable cases = new Hashtable();
2829                 for (int i = 0; i < constants.Length; i++) {
2830                     ConstantMapping c = constants[i];
2831
2832                     CodeIdentifier.CheckValidIdentifier(c.Name);
2833                     if (cases[c.XmlName] == null) {
2834                         Writer.Write("case ");
2835                         WriteQuotedCSharpString(c.XmlName);
2836                         Writer.Write(": return ");
2837                         Writer.Write(RaCodeGen.GetStringForEnumMember(fullTypeName, c.Name, useReflection));
2838                         Writer.WriteLine(";");
2839                         cases[c.XmlName] = c.XmlName;
2840                     }
2841                 }
2842                 
2843                 Writer.Write("default: throw CreateUnknownConstantException(s, ");
2844                 Writer.Write(RaCodeGen.GetStringForTypeof(fullTypeName, useReflection));
2845                 Writer.WriteLine(");");
2846                 Writer.Indent--;
2847                 Writer.WriteLine("}");
2848             }
2849
2850             Writer.Indent--;
2851             Writer.WriteLine("}");
2852         }
2853
2854         void WriteDerivedTypes(StructMapping mapping, bool isTypedReturn, string returnTypeName) {
2855
2856             for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
2857                 Writer.Write("else if (");
2858                 WriteQNameEqual("xsiType", derived.TypeName, derived.Namespace);
2859                 Writer.WriteLine(")");
2860                 Writer.Indent++;
2861
2862                 string methodName = ReferenceMapping(derived);
2863                 #if DEBUG
2864                     // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
2865                     if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, derived.TypeDesc.Name));
2866                 #endif
2867
2868                 Writer.Write("return ");
2869                 if (derived.TypeDesc.UseReflection && isTypedReturn)
2870                     Writer.Write("(" + returnTypeName + ")");
2871                 Writer.Write(methodName);
2872                 Writer.Write("(");
2873                 if (derived.TypeDesc.IsNullable)
2874                     Writer.Write("isNullable, ");
2875                 Writer.WriteLine("false);");
2876
2877                 Writer.Indent--;
2878
2879                 WriteDerivedTypes(derived, isTypedReturn, returnTypeName);
2880             }
2881         }
2882
2883         void WriteEnumAndArrayTypes() {
2884             foreach (TypeScope scope in Scopes) {
2885                 foreach (Mapping m in scope.TypeMappings) {
2886                     if (m.IsSoap)
2887                         continue;
2888                     if (m is EnumMapping) {
2889                         EnumMapping mapping = (EnumMapping)m;
2890                         Writer.Write("else if (");
2891                         WriteQNameEqual("xsiType", mapping.TypeName, mapping.Namespace);
2892                         Writer.WriteLine(") {");
2893                         Writer.Indent++;
2894                         Writer.WriteLine("Reader.ReadStartElement();");
2895                         string methodName = ReferenceMapping(mapping);
2896                         #if DEBUG
2897                             // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
2898                             if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name));
2899                         #endif
2900                         Writer.Write("object e = ");
2901                         Writer.Write(methodName);
2902                         Writer.WriteLine("(CollapseWhitespace(Reader.ReadString()));");
2903                         Writer.WriteLine("ReadEndElement();");
2904                         Writer.WriteLine("return e;");
2905                         Writer.Indent--;
2906                         Writer.WriteLine("}");
2907                     }
2908                     else if (m is ArrayMapping) {
2909                         ArrayMapping mapping = (ArrayMapping) m;
2910                         if (mapping.TypeDesc.HasDefaultConstructor) {
2911                             Writer.Write("else if (");
2912                             WriteQNameEqual("xsiType", mapping.TypeName, mapping.Namespace);
2913                             Writer.WriteLine(") {");
2914                             Writer.Indent++;
2915                             MemberMapping memberMapping = new MemberMapping();
2916                             memberMapping.TypeDesc = mapping.TypeDesc;
2917                             memberMapping.Elements = mapping.Elements;
2918                             Member member = new Member(this,"a", "z", 0, memberMapping);
2919
2920                             TypeDesc td = mapping.TypeDesc;
2921                             string fullTypeName = mapping.TypeDesc.CSharpName;
2922                             if (td.UseReflection){
2923                                 if (td.IsArray)
2924                                     Writer.Write(typeof(Array).FullName);
2925                                 else
2926                                     Writer.Write("object");
2927                             }
2928                             else
2929                                 Writer.Write(fullTypeName);
2930                             Writer.Write(" a = ");
2931                             if (mapping.TypeDesc.IsValueType) {
2932                                 Writer.Write(RaCodeGen.GetStringForCreateInstance(fullTypeName, td.UseReflection, false, false));
2933                                 Writer.WriteLine(";");
2934                             }
2935                             else
2936                                 Writer.WriteLine("null;");
2937
2938                             WriteArray(member.Source, member.ArrayName, mapping, false, false, -1);
2939                             Writer.WriteLine("return a;");
2940                             Writer.Indent--;
2941                             Writer.WriteLine("}");
2942                         }
2943                     }
2944                 }
2945             }
2946         }
2947
2948         void WriteNullableMethod(NullableMapping nullableMapping) {
2949             string methodName = (string)MethodNames[nullableMapping];
2950             bool useReflection = nullableMapping.BaseMapping.TypeDesc.UseReflection;
2951             string typeName = useReflection ? "object" : nullableMapping.TypeDesc.CSharpName;
2952             Writer.WriteLine();
2953
2954             Writer.Write(typeName);
2955             Writer.Write(" ");
2956             Writer.Write(methodName);
2957             Writer.WriteLine("(bool checkType) {");
2958             Writer.Indent++;
2959
2960             Writer.Write(typeName);
2961             Writer.Write(" o = ");
2962
2963             if (useReflection) {
2964                 Writer.Write("null");
2965             }
2966             else {
2967                 Writer.Write("default(");
2968                 Writer.Write(typeName);
2969                 Writer.Write(")");
2970             }
2971             Writer.WriteLine(";");
2972
2973             Writer.WriteLine("if (ReadNull())");
2974             Writer.Indent++;
2975
2976             Writer.WriteLine("return o;");
2977             Writer.Indent--;
2978
2979             ElementAccessor element = new ElementAccessor();
2980             element.Mapping = nullableMapping.BaseMapping;
2981             element.Any = false;
2982             element.IsNullable = nullableMapping.BaseMapping.TypeDesc.IsNullable;
2983
2984             WriteElement("o", null, null, element, null, null, false, false, -1, -1);
2985             Writer.WriteLine("return o;");
2986
2987             Writer.Indent--;
2988             Writer.WriteLine("}");
2989         }
2990
2991         void WriteStructMethod(StructMapping structMapping) {
2992             if (structMapping.IsSoap)
2993                 WriteEncodedStructMethod(structMapping);
2994             else
2995                 WriteLiteralStructMethod(structMapping);
2996         }
2997
2998         void WriteLiteralStructMethod(StructMapping structMapping) {
2999             string methodName = (string)MethodNames[structMapping];
3000             bool useReflection = structMapping.TypeDesc.UseReflection;
3001             string typeName = useReflection ? "object" : structMapping.TypeDesc.CSharpName;
3002             Writer.WriteLine();
3003             Writer.Write(typeName);
3004             Writer.Write(" ");
3005             Writer.Write(methodName);
3006             Writer.Write("(");
3007             if (structMapping.TypeDesc.IsNullable)
3008                 Writer.Write("bool isNullable, ");
3009             Writer.WriteLine("bool checkType) {");
3010             Writer.Indent++;
3011
3012             Writer.Write(typeof(XmlQualifiedName).FullName);
3013             Writer.WriteLine(" xsiType = checkType ? GetXsiType() : null;");
3014             Writer.WriteLine("bool isNull = false;");
3015             if (structMapping.TypeDesc.IsNullable)
3016                 Writer.WriteLine("if (isNullable) isNull = ReadNull();");
3017
3018             Writer.WriteLine("if (checkType) {");
3019             if (structMapping.TypeDesc.IsRoot) {
3020                 Writer.Indent++;
3021                 Writer.WriteLine("if (isNull) {"); 
3022                 Writer.Indent++;
3023                 Writer.WriteLine("if (xsiType != null) return (" + typeName + ")ReadTypedNull(xsiType);"); 
3024                 Writer.Write("else return ");
3025                 if (structMapping.TypeDesc.IsValueType) {
3026                     Writer.Write(RaCodeGen.GetStringForCreateInstance(structMapping.TypeDesc.CSharpName, useReflection, false, false));
3027                     Writer.WriteLine(";");
3028                 }
3029                 else
3030                     Writer.WriteLine("null;");
3031
3032                 Writer.Indent--;
3033                 Writer.WriteLine("}"); 
3034             }
3035             Writer.Write("if (xsiType == null");
3036             if (!structMapping.TypeDesc.IsRoot) {
3037                 Writer.Write(" || ");
3038                 WriteQNameEqual("xsiType", structMapping.TypeName, structMapping.Namespace);
3039             }
3040             Writer.WriteLine(") {");
3041             if (structMapping.TypeDesc.IsRoot) {
3042                 Writer.Indent++;
3043                 Writer.WriteLine("return ReadTypedPrimitive(new System.Xml.XmlQualifiedName(\"" + Soap.UrType + "\", \"" + XmlSchema.Namespace + "\"));");
3044                 Writer.Indent--;
3045             }
3046             Writer.WriteLine("}");
3047             WriteDerivedTypes(structMapping, !useReflection && !structMapping.TypeDesc.IsRoot, typeName);
3048             if (structMapping.TypeDesc.IsRoot) WriteEnumAndArrayTypes();
3049             Writer.WriteLine("else");
3050             Writer.Indent++;
3051             if (structMapping.TypeDesc.IsRoot)
3052                 Writer.Write("return ReadTypedPrimitive((");
3053             else
3054                 Writer.Write("throw CreateUnknownTypeException((");
3055             Writer.Write(typeof(XmlQualifiedName).FullName);
3056             Writer.WriteLine(")xsiType);");
3057             Writer.Indent--;
3058             Writer.WriteLine("}");
3059
3060             if (structMapping.TypeDesc.IsNullable)
3061                 Writer.WriteLine("if (isNull) return null;");
3062
3063             if (structMapping.TypeDesc.IsAbstract) {
3064                 Writer.Write("throw CreateAbstractTypeException(");
3065                 WriteQuotedCSharpString(structMapping.TypeName);
3066                 Writer.Write(", ");
3067                 WriteQuotedCSharpString(structMapping.Namespace);
3068                 Writer.WriteLine(");");
3069             }
3070             else {
3071                 if (structMapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(structMapping.TypeDesc.Type)) {
3072                     Writer.WriteLine("DecodeName = false;");
3073                 }
3074                 WriteCreateMapping(structMapping, "o");
3075                 
3076                 MemberMapping[] mappings = TypeScope.GetSettableMembers(structMapping);
3077                 
3078                 Member anyText = null;
3079                 Member anyElement = null;
3080                 Member anyAttribute = null; 
3081                 bool isSequence = structMapping.HasExplicitSequence();
3082
3083                 ArrayList arraysToDeclareList = new ArrayList(mappings.Length);
3084                 ArrayList arraysToSetList = new ArrayList(mappings.Length);
3085                 ArrayList allMembersList = new ArrayList(mappings.Length);
3086
3087                 for (int i = 0; i < mappings.Length; i++) {
3088                     MemberMapping mapping = mappings[i];
3089                     CodeIdentifier.CheckValidIdentifier(mapping.Name);
3090                     string source = RaCodeGen.GetStringForMember("o", mapping.Name, structMapping.TypeDesc);
3091                     Member member = new Member(this, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
3092                     if (!mapping.IsSequence)
3093                         member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
3094                     member.IsNullable = mapping.TypeDesc.IsNullable;
3095                     if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite)
3096                         member.CheckSpecifiedSource = RaCodeGen.GetStringForMember("o", mapping.Name + "Specified", structMapping.TypeDesc);
3097                     if (mapping.Text != null)
3098                         anyText = member;
3099                     if (mapping.Attribute != null && mapping.Attribute.Any)
3100                         anyAttribute = member;
3101                     if (!isSequence) {
3102                         // find anyElement if present.
3103                         for (int j = 0; j < mapping.Elements.Length; j++) {
3104                             if (mapping.Elements[j].Any && (mapping.Elements[j].Name == null || mapping.Elements[j].Name.Length == 0)) {
3105                                 anyElement = member;
3106                                 break;
3107                             }
3108                         }
3109                     }
3110                     else if (mapping.IsParticle && !mapping.IsSequence) {
3111                         StructMapping declaringMapping;
3112                         structMapping.FindDeclaringMapping(mapping, out declaringMapping, structMapping.TypeName);
3113                         throw new InvalidOperationException(Res.GetString(Res.XmlSequenceHierarchy, structMapping.TypeDesc.FullName, mapping.Name, declaringMapping.TypeDesc.FullName, "Order"));
3114                     }
3115                     if (mapping.Attribute == null && mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping) {
3116                         Member arrayMember = new Member(this, source, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
3117                         arrayMember.CheckSpecifiedSource = member.CheckSpecifiedSource;
3118                         allMembersList.Add(arrayMember);
3119                     }
3120                     else {
3121                         allMembersList.Add(member);
3122                     }
3123
3124                     if (mapping.TypeDesc.IsArrayLike) {
3125                         arraysToDeclareList.Add(member);
3126                         if (mapping.TypeDesc.IsArrayLike && !(mapping.Elements.Length == 1 && mapping.Elements[0].Mapping is ArrayMapping)) {
3127                             member.ParamsReadSource = null; // flat arrays -- don't want to count params read.
3128                             if (member != anyText && member != anyElement) {
3129                                 arraysToSetList.Add(member);
3130                             }
3131                         }
3132                         else if (!mapping.TypeDesc.IsArray) {
3133                             member.ParamsReadSource = null; // collection
3134                         }
3135                     }
3136                 }
3137                 if (anyElement != null) arraysToSetList.Add(anyElement);
3138                 if (anyText != null && anyText != anyElement) arraysToSetList.Add(anyText);
3139
3140                 Member[] arraysToDeclare = (Member[]) arraysToDeclareList.ToArray(typeof(Member));
3141                 Member[] arraysToSet = (Member[]) arraysToSetList.ToArray(typeof(Member));
3142                 Member[] allMembers = (Member[]) allMembersList.ToArray(typeof(Member));
3143
3144                 WriteMemberBegin(arraysToDeclare);
3145                 WriteParamsRead(mappings.Length);
3146
3147                 WriteAttributes(allMembers, anyAttribute, "UnknownNode", "(object)o");
3148                 if (anyAttribute != null)
3149                     WriteMemberEnd(arraysToDeclare);
3150
3151                 Writer.WriteLine("Reader.MoveToElement();");
3152
3153                 Writer.WriteLine("if (Reader.IsEmptyElement) {");
3154                 Writer.Indent++;
3155                 Writer.WriteLine("Reader.Skip();");
3156                 WriteMemberEnd(arraysToSet);
3157                 Writer.WriteLine("return o;");
3158                 Writer.Indent--;
3159                 Writer.WriteLine("}");
3160
3161                 Writer.WriteLine("Reader.ReadStartElement();");
3162                 if (IsSequence(allMembers)) {
3163                     Writer.WriteLine("int state = 0;");
3164                 }
3165                 int loopIndex = WriteWhileNotLoopStart();
3166                 Writer.Indent++;
3167                 string unknownNode = "UnknownNode((object)o, " + ExpectedElements(allMembers) + ");";
3168                 WriteMemberElements(allMembers, unknownNode, unknownNode, anyElement, anyText, null);
3169                 Writer.WriteLine("Reader.MoveToContent();");
3170
3171                 WriteWhileLoopEnd(loopIndex);
3172                 WriteMemberEnd(arraysToSet);
3173
3174                 Writer.WriteLine("ReadEndElement();");
3175                 Writer.WriteLine("return o;");
3176             }
3177             Writer.Indent--;
3178             Writer.WriteLine("}");
3179         }        
3180
3181         void WriteEncodedStructMethod(StructMapping structMapping) {
3182             if(structMapping.TypeDesc.IsRoot)
3183                 return;
3184             bool useReflection = structMapping.TypeDesc.UseReflection;
3185             string methodName = (string)MethodNames[structMapping];
3186             Writer.WriteLine();
3187             Writer.Write("object");
3188             Writer.Write(" ");
3189             Writer.Write(methodName);
3190             Writer.Write("(");
3191             Writer.WriteLine(") {");
3192             Writer.Indent++;
3193
3194             Member[] members;
3195             bool anyFixups;
3196             string fixupMethodName;
3197
3198             if (structMapping.TypeDesc.IsAbstract) {
3199                 Writer.Write("throw CreateAbstractTypeException(");
3200                 WriteQuotedCSharpString(structMapping.TypeName);
3201                 Writer.Write(", ");
3202                 WriteQuotedCSharpString(structMapping.Namespace);
3203                 Writer.WriteLine(");");
3204                 members = new Member[0];
3205                 anyFixups = false;
3206                 fixupMethodName = null;
3207             }
3208             else {
3209                 WriteCreateMapping(structMapping, "o");
3210
3211                 MemberMapping[] mappings = TypeScope.GetSettableMembers(structMapping);
3212                 members = new Member[mappings.Length];
3213                 for (int i = 0; i < mappings.Length; i++) {
3214                     MemberMapping mapping = mappings[i];
3215                     CodeIdentifier.CheckValidIdentifier(mapping.Name);
3216                     string source = RaCodeGen.GetStringForMember("o", mapping.Name, structMapping.TypeDesc);
3217                     Member member = new Member(this,source, source, "a", i, mapping, GetChoiceIdentifierSource(mapping, "o", structMapping.TypeDesc));
3218                     if (mapping.CheckSpecified == SpecifiedAccessor.ReadWrite)
3219                         member.CheckSpecifiedSource = RaCodeGen.GetStringForMember("o", mapping.Name + "Specified", structMapping.TypeDesc);
3220                     if (!mapping.IsSequence)
3221                         member.ParamsReadSource = "paramsRead[" + i.ToString(CultureInfo.InvariantCulture) + "]";
3222                     members[i] = member;
3223                 }
3224
3225                 fixupMethodName = "fixup_" + methodName;
3226                 anyFixups = WriteMemberFixupBegin(members, fixupMethodName, "o");
3227                 
3228                 // we're able to not do WriteMemberBegin here because we don't allow arrays as attributes
3229                 
3230                 WriteParamsRead(mappings.Length);
3231                 WriteAttributes(members, null, "UnknownNode", "(object)o");
3232                 Writer.WriteLine("Reader.MoveToElement();");
3233
3234                 Writer.WriteLine("if (Reader.IsEmptyElement) { Reader.Skip(); return o; }");
3235                 Writer.WriteLine("Reader.ReadStartElement();");
3236
3237                 int loopIndex = WriteWhileNotLoopStart();
3238                 Writer.Indent++;
3239
3240                 WriteMemberElements(members, "UnknownNode((object)o);", "UnknownNode((object)o);", null, null, null);
3241                 Writer.WriteLine("Reader.MoveToContent();");
3242
3243                 WriteWhileLoopEnd(loopIndex);
3244
3245                 Writer.WriteLine("ReadEndElement();");
3246                 Writer.WriteLine("return o;");
3247             }
3248             Writer.Indent--;
3249             Writer.WriteLine("}");
3250
3251             if (anyFixups) WriteFixupMethod(fixupMethodName, members, structMapping.TypeDesc.CSharpName, structMapping.TypeDesc.UseReflection, true, "o");
3252         }
3253
3254         void WriteFixupMethod(string fixupMethodName, Member[] members, string typeName, bool useReflection, bool typed, string source) {
3255             Writer.WriteLine();
3256             Writer.Write("void ");
3257             Writer.Write(fixupMethodName);
3258             Writer.WriteLine("(object objFixup) {");
3259             Writer.Indent++;
3260             Writer.WriteLine("Fixup fixup = (Fixup)objFixup;");
3261             WriteLocalDecl(typeName, source, "fixup.Source", useReflection);
3262             Writer.WriteLine("string[] ids = fixup.Ids;");
3263
3264             for (int i = 0; i < members.Length; i++) {
3265                 Member member = members[i];
3266                 if (member.MultiRef) {
3267                     string fixupIndex = member.FixupIndex.ToString(CultureInfo.InvariantCulture);
3268                     Writer.Write("if (ids[");
3269                     Writer.Write(fixupIndex);
3270                     Writer.WriteLine("] != null) {");
3271                     Writer.Indent++;
3272
3273                     string memberSource = /*member.IsList ? source + ".Add(" :*/ member.ArraySource;
3274
3275                     string targetSource = "GetTarget(ids[" + fixupIndex + "])";
3276                     TypeDesc td = member.Mapping.TypeDesc;
3277                     if (td.IsCollection || td.IsEnumerable) {
3278                         WriteAddCollectionFixup(td, member.Mapping.ReadOnly, memberSource, targetSource);
3279                     }
3280                     else {
3281                         if (typed) {
3282                             Writer.WriteLine("try {");
3283                             Writer.Indent++;
3284                             WriteSourceBeginTyped(memberSource, member.Mapping.TypeDesc);
3285                         }
3286                         else
3287                             WriteSourceBegin(memberSource);
3288
3289                         Writer.Write(targetSource);
3290                         WriteSourceEnd(memberSource);
3291                         Writer.WriteLine(";");
3292
3293                         if (member.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite && member.CheckSpecifiedSource != null && member.CheckSpecifiedSource.Length > 0) { 
3294                             Writer.Write(member.CheckSpecifiedSource);
3295                             Writer.WriteLine(" = true;");
3296                         }
3297
3298                         if (typed) {
3299                             WriteCatchCastException(member.Mapping.TypeDesc, targetSource, "ids[" + fixupIndex + "]");
3300                         }
3301                     }
3302                     Writer.Indent--;
3303                     Writer.WriteLine("}");
3304                 }
3305             }
3306             Writer.Indent--;
3307             Writer.WriteLine("}");
3308         }
3309
3310         void WriteAddCollectionFixup(TypeDesc typeDesc, bool readOnly, string memberSource, string targetSource) {
3311             Writer.WriteLine("// get array of the collection items");
3312             bool useReflection = typeDesc.UseReflection;
3313             CreateCollectionInfo create = (CreateCollectionInfo)createMethods[typeDesc];
3314             if (create == null) {
3315                 string createName = "create" + (++nextCreateMethodNumber).ToString(CultureInfo.InvariantCulture) + "_" + typeDesc.Name;
3316                 create = new CreateCollectionInfo(createName, typeDesc);
3317                 createMethods.Add(typeDesc, create);
3318             }
3319
3320             Writer.Write("if ((object)(");
3321             Writer.Write(memberSource);
3322             Writer.WriteLine(") == null) {");
3323             Writer.Indent++;
3324
3325             if (readOnly) {
3326                 Writer.Write("throw CreateReadOnlyCollectionException(");
3327                 WriteQuotedCSharpString(typeDesc.CSharpName);
3328                 Writer.WriteLine(");");
3329             }
3330             else {
3331                 Writer.Write(memberSource);
3332                 Writer.Write(" = ");
3333                 Writer.Write(RaCodeGen.GetStringForCreateInstance(typeDesc.CSharpName, typeDesc.UseReflection, typeDesc.CannotNew, true));
3334                 Writer.WriteLine(";");
3335             }
3336
3337             Writer.Indent--;
3338             Writer.WriteLine("}");
3339         
3340             Writer.Write("CollectionFixup collectionFixup = new CollectionFixup(");
3341             Writer.Write(memberSource);
3342             Writer.Write(", ");
3343             Writer.Write("new ");
3344             Writer.Write(typeof(XmlSerializationCollectionFixupCallback).FullName);
3345             Writer.Write("(this.");
3346             Writer.Write(create.Name);
3347             Writer.Write("), ");
3348             Writer.Write(targetSource);
3349             Writer.WriteLine(");");
3350             Writer.WriteLine("AddFixup(collectionFixup);");
3351         }
3352
3353         void WriteCreateCollectionMethod(CreateCollectionInfo c) {
3354             Writer.Write("void ");
3355             Writer.Write(c.Name);
3356             Writer.WriteLine("(object collection, object collectionItems) {");
3357             Writer.Indent++;
3358
3359             Writer.WriteLine("if (collectionItems == null) return;");
3360             Writer.WriteLine("if (collection == null) return;");
3361
3362             TypeDesc td = c.TypeDesc;
3363             bool useReflection = td.UseReflection;
3364             string fullTypeName = td.CSharpName;
3365             WriteLocalDecl(fullTypeName, "c", "collection", useReflection);
3366
3367             WriteCreateCollection(td, "collectionItems");
3368
3369             Writer.Indent--;
3370             Writer.WriteLine("}");
3371         }
3372
3373         void WriteQNameEqual(string source, string name, string ns) {
3374             Writer.Write("((object) ((");
3375             Writer.Write(typeof(XmlQualifiedName).FullName);
3376             Writer.Write(")");
3377             Writer.Write(source);
3378             Writer.Write(").Name == (object)");
3379             WriteID(name);
3380             Writer.Write(" && (object) ((");
3381             Writer.Write(typeof(XmlQualifiedName).FullName);
3382             Writer.Write(")");
3383             Writer.Write(source);
3384             Writer.Write(").Namespace == (object)");
3385             WriteID(ns);
3386             Writer.Write(")");
3387         }
3388
3389         void WriteXmlNodeEqual(string source, string name, string ns) {
3390             Writer.Write("(");
3391             if (name != null && name.Length > 0) {
3392                 Writer.Write("(object) ");
3393                 Writer.Write(source);
3394                 Writer.Write(".LocalName == (object)");
3395                 WriteID(name);
3396                 Writer.Write(" && ");
3397             }
3398             Writer.Write("(object) ");
3399             Writer.Write(source);
3400             Writer.Write(".NamespaceURI == (object)");
3401             WriteID(ns);
3402             Writer.Write(")");
3403         }
3404
3405         void WriteID(string name) {
3406             if (name == null) {
3407                 //Writer.Write("null");
3408                 //return;
3409                 name = "";
3410             }
3411             string idName = (string)idNames[name];
3412             if (idName == null) {
3413                 idName = NextIdName(name);
3414                 idNames.Add(name, idName);
3415             }
3416             Writer.Write(idName);
3417         }
3418
3419         void WriteAttributes(Member[] members, Member anyAttribute, string elseCall, string firstParam) {
3420             int count = 0;
3421             Member xmlnsMember = null;
3422             ArrayList attributes = new ArrayList();
3423             
3424             Writer.WriteLine("while (Reader.MoveToNextAttribute()) {");
3425             Writer.Indent++;
3426
3427             for (int i = 0; i < members.Length; i++) {
3428                 Member member = (Member)members[i];
3429                 if (member.Mapping.Xmlns != null) {
3430                     xmlnsMember = member;
3431                     continue;
3432                 }
3433                 if (member.Mapping.Ignore)
3434                     continue;
3435                 AttributeAccessor attribute = member.Mapping.Attribute;
3436
3437                 if (attribute == null) continue;
3438                 if (attribute.Any) continue;
3439
3440                 attributes.Add(attribute);
3441
3442                 if (count++ > 0)
3443                     Writer.Write("else ");
3444
3445                 Writer.Write("if (");
3446                 if (member.ParamsReadSource != null) {
3447                     Writer.Write("!");
3448                     Writer.Write(member.ParamsReadSource);
3449                     Writer.Write(" && ");
3450                 }
3451
3452                 if (attribute.IsSpecialXmlNamespace) {
3453                     WriteXmlNodeEqual("Reader", attribute.Name, XmlReservedNs.NsXml);
3454                 }
3455                 else
3456                     WriteXmlNodeEqual("Reader", attribute.Name, attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "");
3457                 Writer.WriteLine(") {");
3458                 Writer.Indent++;
3459
3460                 WriteAttribute(member);
3461                 Writer.Indent--;
3462                 Writer.WriteLine("}");
3463             }
3464
3465             if (count > 0)
3466                 Writer.Write("else ");
3467
3468             if (xmlnsMember != null) {
3469                 Writer.WriteLine("if (IsXmlnsAttribute(Reader.Name)) {");
3470                 Writer.Indent++;
3471
3472                 Writer.Write("if (");
3473                 Writer.Write(xmlnsMember.Source);
3474                 Writer.Write(" == null) ");
3475                 Writer.Write(xmlnsMember.Source);
3476                 Writer.Write(" = new ");
3477                 Writer.Write(xmlnsMember.Mapping.TypeDesc.CSharpName);
3478                 Writer.WriteLine("();");
3479
3480                 //Writer.Write(xmlnsMember.ArraySource);
3481                 Writer.Write("(("+xmlnsMember.Mapping.TypeDesc.CSharpName+")"+ xmlnsMember.ArraySource+")");
3482                 Writer.WriteLine(".Add(Reader.Name.Length == 5 ? \"\" : Reader.LocalName, Reader.Value);");
3483
3484                 Writer.Indent--;
3485                 Writer.WriteLine("}");
3486
3487                 Writer.WriteLine("else {");
3488                 Writer.Indent++;
3489             }
3490             else {
3491                 Writer.WriteLine("if (!IsXmlnsAttribute(Reader.Name)) {");
3492                 Writer.Indent++;
3493             }
3494             if (anyAttribute != null) {
3495                 Writer.Write(typeof(XmlAttribute).FullName);
3496                 Writer.Write(" attr = ");
3497                 Writer.Write("(");
3498                 Writer.Write(typeof(XmlAttribute).FullName);
3499                 Writer.WriteLine(") Document.ReadNode(Reader);");
3500                 Writer.WriteLine("ParseWsdlArrayType(attr);");
3501                 WriteAttribute(anyAttribute);
3502             }
3503             else {
3504                 Writer.Write(elseCall);
3505                 Writer.Write("(");
3506                 Writer.Write(firstParam);
3507                 if (attributes.Count > 0) {
3508                     Writer.Write(", ");
3509                     string qnames = "";
3510
3511                     for (int i = 0; i < attributes.Count; i++) {
3512                         AttributeAccessor attribute = (AttributeAccessor)attributes[i];
3513                         if (i > 0)
3514                             qnames += ", ";
3515                         qnames += attribute.IsSpecialXmlNamespace ? XmlReservedNs.NsXml : (attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "") + ":" + attribute.Name;
3516                     }
3517                     WriteQuotedCSharpString(qnames);
3518                 }
3519                 Writer.WriteLine(");");
3520             }
3521             Writer.Indent--;
3522             Writer.WriteLine("}");
3523
3524             Writer.Indent--;
3525             Writer.WriteLine("}");
3526         }
3527
3528         void WriteAttribute(Member member) {
3529
3530             AttributeAccessor attribute = member.Mapping.Attribute;
3531
3532             if (attribute.Mapping is SpecialMapping) {
3533                 SpecialMapping special = (SpecialMapping)attribute.Mapping;
3534                     
3535                 if (special.TypeDesc.Kind == TypeKind.Attribute) {
3536                     WriteSourceBegin(member.ArraySource);
3537                     Writer.Write("attr");
3538                     WriteSourceEnd(member.ArraySource);
3539                     Writer.WriteLine(";");
3540                 }
3541                 else if (special.TypeDesc.CanBeAttributeValue) {
3542                     Writer.Write("if (attr is ");
3543                     Writer.Write(typeof(XmlAttribute).FullName);
3544                     Writer.WriteLine(") {");
3545                     Writer.Indent++;
3546                     WriteSourceBegin(member.ArraySource);
3547                     Writer.Write("(");
3548                     Writer.Write(typeof(XmlAttribute).FullName);
3549                     Writer.Write(")attr");
3550                     WriteSourceEnd(member.ArraySource);
3551                     Writer.WriteLine(";");
3552                     Writer.Indent--;
3553                     Writer.WriteLine("}");
3554                 }
3555                 else
3556                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
3557             }
3558             else {
3559                 if (attribute.IsList) {
3560                     Writer.WriteLine("string listValues = Reader.Value;");
3561                     Writer.WriteLine("string[] vals = listValues.Split(null);");
3562                     Writer.WriteLine("for (int i = 0; i < vals.Length; i++) {");
3563                     Writer.Indent++;
3564
3565                     string attributeSource = GetArraySource(member.Mapping.TypeDesc, member.ArrayName);
3566
3567                     WriteSourceBegin(attributeSource);
3568                     WritePrimitive(attribute.Mapping, "vals[i]");
3569                     WriteSourceEnd(attributeSource);
3570                     Writer.WriteLine(";");
3571                     Writer.Indent--;
3572                     Writer.WriteLine("}");
3573                 }
3574                 else {
3575                     WriteSourceBegin(member.ArraySource);
3576                     WritePrimitive(attribute.Mapping, attribute.IsList ? "vals[i]" : "Reader.Value");
3577                     WriteSourceEnd(member.ArraySource);
3578                     Writer.WriteLine(";");
3579                 }
3580             }
3581             if (member.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite && member.CheckSpecifiedSource != null && member.CheckSpecifiedSource.Length > 0) { 
3582                 Writer.Write(member.CheckSpecifiedSource);
3583                 Writer.WriteLine(" = true;");
3584             }
3585             if (member.ParamsReadSource != null) {
3586                 Writer.Write(member.ParamsReadSource);
3587                 Writer.WriteLine(" = true;");
3588             }
3589         }
3590
3591         bool WriteMemberFixupBegin(Member[] members, string fixupMethodName, string source) {
3592             int fixupCount = 0;
3593             for (int i = 0; i < members.Length; i++) {
3594                 Member member = (Member)members[i];
3595                 if (member.Mapping.Elements.Length == 0)
3596                     continue;
3597
3598                 TypeMapping mapping = member.Mapping.Elements[0].Mapping;
3599                 if (mapping is StructMapping || mapping is ArrayMapping || mapping is PrimitiveMapping || mapping is NullableMapping) {
3600                     member.MultiRef = true;
3601                     member.FixupIndex = fixupCount++;
3602                 }
3603             }
3604
3605             if (fixupCount > 0) {
3606                 Writer.Write("Fixup fixup = new Fixup(");
3607                 Writer.Write(source);
3608                 Writer.Write(", ");
3609                 Writer.Write("new ");
3610                 Writer.Write(typeof(XmlSerializationFixupCallback).FullName);
3611                 Writer.Write("(this.");
3612                 Writer.Write(fixupMethodName);
3613                 Writer.Write("), ");
3614                 Writer.Write(fixupCount.ToString(CultureInfo.InvariantCulture));
3615                 Writer.WriteLine(");");
3616                 Writer.WriteLine("AddFixup(fixup);");
3617                 return true;
3618             }
3619             return false;
3620         }
3621
3622         void WriteMemberBegin(Member[] members) {
3623
3624             for (int i = 0; i < members.Length; i++) {
3625                 Member member = (Member)members[i];
3626
3627                 if (member.IsArrayLike) {
3628                     string a = member.ArrayName;
3629                     string c = "c" + a;
3630
3631                     TypeDesc typeDesc = member.Mapping.TypeDesc;
3632                     string typeDescFullName = typeDesc.CSharpName;
3633                 
3634                     if (member.Mapping.TypeDesc.IsArray) {
3635                         WriteArrayLocalDecl(typeDesc.CSharpName,
3636                                             a, "null", typeDesc);
3637                         Writer.Write("int ");
3638                         Writer.Write(c);
3639                         Writer.WriteLine(" = 0;");
3640
3641                         if (member.Mapping.ChoiceIdentifier != null) {
3642                             WriteArrayLocalDecl(member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.CSharpName+"[]",
3643                                                 member.ChoiceArrayName, "null",
3644                                                 member.Mapping.ChoiceIdentifier.Mapping.TypeDesc);
3645                             Writer.Write("int c");
3646                             Writer.Write(member.ChoiceArrayName);
3647                             Writer.WriteLine(" = 0;");
3648
3649                         }
3650                     }
3651                     else {
3652                         bool useReflection = typeDesc.UseReflection;
3653                         if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{') {
3654                             WriteCreateInstance(typeDescFullName, a, useReflection, typeDesc.CannotNew); 
3655                             Writer.Write(member.Source);
3656                             Writer.Write(a);
3657                             if (member.Source[member.Source.Length - 1] == '{')
3658                                 Writer.WriteLine("});");
3659                             else
3660                                 Writer.WriteLine(");");
3661                         }
3662                         else {
3663                             if (member.IsList && !member.Mapping.ReadOnly && member.Mapping.TypeDesc.IsNullable) {
3664                                 // we need to new the Collections and ArrayLists
3665                                 Writer.Write("if ((object)(");
3666                                 Writer.Write(member.Source);
3667                                 Writer.Write(") == null) ");
3668                                 if (!member.Mapping.TypeDesc.HasDefaultConstructor) {
3669                                     Writer.Write("throw CreateReadOnlyCollectionException(");
3670                                     WriteQuotedCSharpString(member.Mapping.TypeDesc.CSharpName);
3671                                     Writer.WriteLine(");");
3672                                 }
3673                                 else {
3674                                     Writer.Write(member.Source);
3675                                     Writer.Write(" = ");
3676                                     Writer.Write(RaCodeGen.GetStringForCreateInstance(typeDescFullName, useReflection, typeDesc.CannotNew, true));
3677                                     Writer.WriteLine(";");
3678                                 }
3679                             }
3680                             WriteLocalDecl(typeDescFullName, a, member.Source, useReflection);
3681                         }
3682                     }
3683                 }
3684             }
3685         }
3686
3687         string ExpectedElements(Member[] members) {
3688             if (IsSequence(members))
3689                 return "null";
3690             string qnames = string.Empty;
3691             bool firstElement = true;
3692             for (int i = 0; i < members.Length; i++) {
3693                 Member member = (Member)members[i];
3694                 if (member.Mapping.Xmlns != null)
3695                     continue;
3696                 if (member.Mapping.Ignore)
3697                     continue;
3698                 if (member.Mapping.IsText || member.Mapping.IsAttribute)
3699                     continue;
3700                 
3701                 ElementAccessor[] elements = member.Mapping.Elements;
3702
3703                 for (int j = 0; j < elements.Length; j++) {
3704                     ElementAccessor e = elements[j];
3705                     string ns = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
3706                     if (e.Any && (e.Name == null || e.Name.Length == 0)) continue;
3707
3708                     if (!firstElement)
3709                         qnames += ", ";
3710                     qnames += ns + ":" + e.Name;
3711                     firstElement = false;
3712                 }
3713             }
3714             StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
3715             ReflectionAwareCodeGen.WriteQuotedCSharpString(new IndentedWriter(writer, true), qnames);
3716             return writer.ToString();
3717         }
3718
3719         void WriteMemberElements(Member[] members, string elementElseString, string elseString, Member anyElement, Member anyText, string checkTypeHrefsSource) {
3720             bool checkType = (checkTypeHrefsSource != null && checkTypeHrefsSource.Length > 0);
3721
3722             if (anyText != null) {
3723                 Writer.WriteLine("string tmp = null;");
3724             }
3725
3726             Writer.Write("if (Reader.NodeType == ");
3727             Writer.Write(typeof(XmlNodeType).FullName);
3728             Writer.WriteLine(".Element) {");
3729             Writer.Indent++;
3730
3731             if (checkType) {
3732                 WriteIfNotSoapRoot(elementElseString + " continue;");
3733                 WriteMemberElementsCheckType(checkTypeHrefsSource);
3734             }
3735             else {
3736                 WriteMemberElementsIf(members, anyElement, elementElseString, null);
3737             }
3738
3739             Writer.Indent--;
3740             Writer.WriteLine("}");
3741
3742             if (anyText != null)
3743                 WriteMemberText(anyText, elseString);
3744
3745             Writer.WriteLine("else {");
3746             Writer.Indent++;
3747             Writer.WriteLine(elseString);
3748             Writer.Indent--;
3749             Writer.WriteLine("}");
3750         }
3751
3752         void WriteMemberText(Member anyText, string elseString) {
3753             Writer.Write("else if (Reader.NodeType == ");
3754             Writer.Write(typeof(XmlNodeType).FullName);
3755             Writer.WriteLine(".Text || ");
3756             Writer.Write("Reader.NodeType == ");
3757             Writer.Write(typeof(XmlNodeType).FullName);
3758             Writer.WriteLine(".CDATA || ");
3759             Writer.Write("Reader.NodeType == ");
3760             Writer.Write(typeof(XmlNodeType).FullName);
3761             Writer.WriteLine(".Whitespace || ");
3762             Writer.Write("Reader.NodeType == ");
3763             Writer.Write(typeof(XmlNodeType).FullName);
3764             Writer.WriteLine(".SignificantWhitespace) {");
3765             Writer.Indent++;
3766
3767             if (anyText != null) {
3768                 WriteText(anyText);
3769             }
3770             else {
3771                 Writer.Write(elseString);
3772                 Writer.WriteLine(";");
3773             }
3774             Writer.Indent--;
3775             Writer.WriteLine("}");
3776         }
3777
3778         void WriteText(Member member) {
3779
3780             TextAccessor text = member.Mapping.Text;
3781
3782             if (text.Mapping is SpecialMapping) {
3783                 SpecialMapping special = (SpecialMapping)text.Mapping;
3784                 WriteSourceBeginTyped(member.ArraySource, special.TypeDesc);
3785                 switch (special.TypeDesc.Kind) {
3786                     case TypeKind.Node:
3787                         Writer.Write("Document.CreateTextNode(Reader.ReadString())");
3788                         break;
3789                     default:
3790                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
3791                 }
3792                 WriteSourceEnd(member.ArraySource);
3793             }
3794             else {
3795                 if (member.IsArrayLike) {
3796                     WriteSourceBegin(member.ArraySource);
3797                     if (text.Mapping.TypeDesc.CollapseWhitespace) {
3798                         Writer.Write("CollapseWhitespace(Reader.ReadString())");
3799                     }
3800                     else {
3801                         Writer.Write("Reader.ReadString()");
3802                     }
3803                 }
3804                 else {
3805                     if (text.Mapping.TypeDesc == StringTypeDesc || text.Mapping.TypeDesc.FormatterName == "String") {
3806                         Writer.Write("tmp = ReadString(tmp, ");
3807                         if (text.Mapping.TypeDesc.CollapseWhitespace)
3808                             Writer.WriteLine("true);");
3809                         else 
3810                             Writer.WriteLine("false);");
3811                         
3812                         WriteSourceBegin(member.ArraySource);
3813                         Writer.Write("tmp");
3814                     }
3815                     else {
3816                         WriteSourceBegin(member.ArraySource);
3817                         WritePrimitive(text.Mapping, "Reader.ReadString()");
3818                     }
3819                 }
3820                 WriteSourceEnd(member.ArraySource);
3821             }
3822
3823             Writer.WriteLine(";");
3824         }
3825
3826         void WriteMemberElementsCheckType(string checkTypeHrefsSource) {
3827             Writer.WriteLine("string refElemId = null;");
3828             Writer.WriteLine("object refElem = ReadReferencingElement(null, null, true, out refElemId);");
3829             
3830             Writer.WriteLine("if (refElemId != null) {");
3831             Writer.Indent++;
3832             Writer.Write(checkTypeHrefsSource);
3833             Writer.WriteLine(".Add(refElemId);");
3834             Writer.Write(checkTypeHrefsSource);
3835             Writer.WriteLine("IsObject.Add(false);");
3836             Writer.Indent--;
3837             Writer.WriteLine("}");
3838             Writer.WriteLine("else if (refElem != null) {");
3839             Writer.Indent++;
3840             Writer.Write(checkTypeHrefsSource);
3841             Writer.WriteLine(".Add(refElem);");
3842             Writer.Write(checkTypeHrefsSource);
3843             Writer.WriteLine("IsObject.Add(true);");
3844             Writer.Indent--;
3845             Writer.WriteLine("}");
3846         }
3847
3848         void WriteMemberElementsElse(Member anyElement, string elementElseString) {
3849             if (anyElement != null) {
3850                 ElementAccessor[] elements = anyElement.Mapping.Elements;
3851                 for (int i = 0; i < elements.Length; i++) {
3852                     ElementAccessor element = elements[i];
3853                     if (element.Any && element.Name.Length == 0) {
3854                         WriteElement(anyElement.ArraySource, anyElement.ArrayName, anyElement.ChoiceArraySource, element, anyElement.Mapping.ChoiceIdentifier, anyElement.Mapping.CheckSpecified == SpecifiedAccessor.ReadWrite ? anyElement.CheckSpecifiedSource : null, false, false, -1, i);
3855                         break;
3856                     }
3857                 }
3858             }
3859             else {
3860                 Writer.WriteLine(elementElseString);
3861             }
3862         }
3863
3864         bool IsSequence(Member[] members) {
3865             for (int i = 0; i < members.Length; i++) {
3866                 if (members[i].Mapping.IsParticle && members[i].Mapping.IsSequence)
3867                     return true;
3868             }
3869             return false;
3870         }
3871         void WriteMemberElementsIf(Member[] members, Member anyElement, string elementElseString, string checkTypeSource) {
3872             bool checkType = checkTypeSource != null && checkTypeSource.Length > 0;
3873             //int count = checkType ? 1 : 0;
3874             int count = 0;
3875
3876             bool isSequence = IsSequence(members);
3877             if (isSequence) {
3878                 Writer.WriteLine("switch (state) {");
3879             }
3880             int cases = 0;
3881
3882             for (int i = 0; i < members.Length; i++) {
3883                 Member member = (Member)members[i];
3884                 if (member.Mapping.Xmlns != null)
3885                     continue;
3886                 if (member.Mapping.Ignore)
3887                     continue;
3888                 if (isSequence && (member.Mapping.IsText || member.Mapping.IsAttribute))
3889                     continue;
3890
3891                 bool firstElement = true;
3892                 ChoiceIdentifierAccessor choice = member.Mapping.ChoiceIdentifier;
3893                 ElementAccessor[] elements = member.Mapping.Elements;
3894
3895                 for (int j = 0; j < elements.Length; j++) {
3896                     ElementAccessor e = elements[j];
3897                     string ns = e.Form == XmlSchemaForm.Qualified ? e.Namespace : "";
3898                     if (!isSequence && e.Any && (e.Name == null || e.Name.Length == 0)) continue;
3899                     if (!firstElement || (!isSequence && count > 0)) {
3900                         Writer.Write("else ");
3901                     }
3902                     else if (isSequence) {
3903                         Writer.Write("case ");
3904                         Writer.Write(cases.ToString(CultureInfo.InvariantCulture));
3905                         Writer.WriteLine(":");
3906                         Writer.Indent++;
3907                     }
3908                     count++;
3909                     firstElement = false;
3910                     Writer.Write("if (");
3911                     if (member.ParamsReadSource != null) {
3912                         Writer.Write("!");
3913                         Writer.Write(member.ParamsReadSource);
3914                         Writer.Write(" && ");
3915                     }
3916                     if (checkType) {
3917                         if (e.Mapping is NullableMapping) {
3918                             TypeDesc td = ((NullableMapping)e.Mapping).BaseMapping.TypeDesc;
3919                             Writer.Write(RaCodeGen.GetStringForTypeof(td.CSharpName, td.UseReflection));
3920                         }
3921                         else {
3922                             Writer.Write(RaCodeGen.GetStringForTypeof(e.Mapping.TypeDesc.CSharpName, e.Mapping.TypeDesc.UseReflection));
3923                         }
3924                         Writer.Write(".IsAssignableFrom(");
3925                         Writer.Write(checkTypeSource);
3926                         Writer.Write("Type)");
3927                     }
3928                     else {
3929                         if (member.Mapping.IsReturnValue)
3930                             Writer.Write("(IsReturnValue || ");
3931                         if (isSequence && e.Any && e.AnyNamespaces == null) {
3932                             Writer.Write("true");
3933                         }
3934                         else {
3935                             WriteXmlNodeEqual("Reader", e.Name, ns);
3936                         }
3937                         if (member.Mapping.IsReturnValue)
3938                             Writer.Write(")");
3939                     }
3940                     Writer.WriteLine(") {");
3941                     Writer.Indent++;
3942                     if (checkType) {
3943                         if (e.Mapping.TypeDesc.IsValueType || e.Mapping is NullableMapping) {
3944                             Writer.Write("if (");
3945                             Writer.Write(checkTypeSource);
3946                             Writer.WriteLine(" != null) {");
3947                             Writer.Indent++;
3948                         }
3949                         if (e.Mapping is NullableMapping) {
3950                             WriteSourceBegin(member.ArraySource);
3951                             TypeDesc td = ((NullableMapping)e.Mapping).BaseMapping.TypeDesc;
3952                             Writer.Write(RaCodeGen.GetStringForCreateInstance(e.Mapping.TypeDesc.CSharpName, e.Mapping.TypeDesc.UseReflection, false, true, "(" + td.CSharpName + ")" + checkTypeSource));
3953                         }
3954                         else {
3955                             WriteSourceBeginTyped(member.ArraySource, e.Mapping.TypeDesc);
3956                             Writer.Write(checkTypeSource); 
3957                         }
3958                         WriteSourceEnd(member.ArraySource);
3959                         Writer.WriteLine(";");
3960                         if (e.Mapping.TypeDesc.IsValueType) {
3961                             Writer.Indent--;
3962                             Writer.WriteLine("}");
3963                         }
3964                         if (member.FixupIndex >= 0) {
3965                             Writer.Write("fixup.Ids[");
3966                             Writer.Write(member.FixupIndex.ToString(CultureInfo.InvariantCulture));
3967                             Writer.Write("] = ");
3968                             Writer.Write(checkTypeSource);
3969                             Writer.WriteLine("Id;");
3970                         }
3971                     }
3972                     else {
3973                         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);
3974                     }
3975                     if (member.Mapping.IsReturnValue)
3976                         Writer.WriteLine("IsReturnValue = false;");
3977                     if (member.ParamsReadSource != null) {
3978                         Writer.Write(member.ParamsReadSource);
3979                         Writer.WriteLine(" = true;");
3980                     }
3981                     Writer.Indent--;
3982                     Writer.WriteLine("}");
3983                 }
3984                 if (isSequence) {
3985                     if (member.IsArrayLike) {
3986                         Writer.WriteLine("else {");
3987                         Writer.Indent++;
3988                     }
3989                     cases++;
3990                     Writer.Write("state = ");
3991                     Writer.Write(cases.ToString(CultureInfo.InvariantCulture));
3992                     Writer.WriteLine(";");
3993                     if (member.IsArrayLike) {
3994                         Writer.Indent--;
3995                         Writer.WriteLine("}");
3996                     }
3997                     Writer.WriteLine("break;");
3998                     Writer.Indent--;
3999                 }
4000             }
4001             if (count > 0) {
4002                 if (isSequence)
4003                     Writer.WriteLine("default:");
4004                 else 
4005                     Writer.WriteLine("else {");
4006                 Writer.Indent++;
4007             }
4008             WriteMemberElementsElse(anyElement, elementElseString);
4009             if (count > 0) {
4010                 if (isSequence) {
4011                     Writer.WriteLine("break;");
4012                 }
4013                 Writer.Indent--;
4014                 Writer.WriteLine("}");
4015             }
4016         }
4017
4018         string GetArraySource(TypeDesc typeDesc, string arrayName) {
4019             return GetArraySource(typeDesc, arrayName, false);
4020         }
4021         string GetArraySource(TypeDesc typeDesc, string arrayName, bool multiRef) {
4022             string a = arrayName;
4023             string c = "c" + a;
4024             string init = "";
4025
4026             if (multiRef) {
4027                 init = "soap = (System.Object[])EnsureArrayIndex(soap, " + c + "+2, typeof(System.Object)); ";
4028             }
4029             bool useReflection = typeDesc.UseReflection;
4030             if (typeDesc.IsArray) {
4031                 string arrayTypeFullName = typeDesc.ArrayElementTypeDesc.CSharpName;
4032                 bool arrayUseReflection = typeDesc.ArrayElementTypeDesc.UseReflection;
4033                 string castString = useReflection?"":"(" + arrayTypeFullName + "[])";
4034                 init = init + a + " = " + castString +
4035                     "EnsureArrayIndex(" + a + ", " + c + ", "+ RaCodeGen.GetStringForTypeof(arrayTypeFullName, arrayUseReflection) + ");";
4036                 string arraySource = RaCodeGen.GetStringForArrayMember(a, c+"++", typeDesc);
4037                 if (multiRef) {
4038                     init = init + " soap[1] = " + a + ";";
4039                     init = init + " if (ReadReference(out soap[" + c + "+2])) " + arraySource + " = null; else ";
4040                 }
4041                 return init + arraySource;
4042             }
4043             else {
4044                 return RaCodeGen.GetStringForMethod(arrayName,typeDesc.CSharpName,"Add",useReflection);
4045                 
4046             }
4047         }
4048
4049
4050         void WriteMemberEnd(Member[] members) {
4051             WriteMemberEnd(members, false);
4052         }
4053
4054         void WriteMemberEnd(Member[] members, bool soapRefs) {
4055             for (int i = 0; i < members.Length; i++) {
4056                 Member member = (Member)members[i];
4057
4058                 if (member.IsArrayLike) {
4059
4060                     TypeDesc typeDesc = member.Mapping.TypeDesc;
4061
4062                     if (typeDesc.IsArray) {
4063
4064                         WriteSourceBegin(member.Source);
4065
4066                         if (soapRefs)
4067                             Writer.Write(" soap[1] = ");
4068
4069                         string a = member.ArrayName;
4070                         string c = "c" + a;
4071                         
4072                         bool arrayUseReflection = typeDesc.ArrayElementTypeDesc.UseReflection;
4073                         string arrayTypeFullName = typeDesc.ArrayElementTypeDesc.CSharpName;
4074                         if (!arrayUseReflection)
4075                             Writer.Write("(" +arrayTypeFullName +"[])");
4076                         Writer.Write("ShrinkArray(");
4077                         Writer.Write(a);
4078                         Writer.Write(", ");
4079                         Writer.Write(c);
4080                         Writer.Write(", ");
4081                         Writer.Write(RaCodeGen.GetStringForTypeof(arrayTypeFullName, arrayUseReflection));
4082                         Writer.Write(", ");
4083                         WriteBooleanValue(member.IsNullable);
4084                         Writer.Write(")");
4085                         WriteSourceEnd(member.Source);
4086                         Writer.WriteLine(";");
4087
4088                         if (member.Mapping.ChoiceIdentifier != null) {
4089                             WriteSourceBegin(member.ChoiceSource);
4090                             a = member.ChoiceArrayName;
4091                             c = "c" + a;
4092                         
4093                             bool choiceUseReflection = member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.UseReflection;
4094                             string choiceTypeName = member.Mapping.ChoiceIdentifier.Mapping.TypeDesc.CSharpName;
4095                             if(!choiceUseReflection)
4096                                 Writer.Write("(" +choiceTypeName+"[])");
4097                             Writer.Write("ShrinkArray(");
4098                             Writer.Write(a);
4099                             Writer.Write(", ");
4100                             Writer.Write(c);
4101                             Writer.Write(", ");
4102                             Writer.Write(RaCodeGen.GetStringForTypeof(choiceTypeName, choiceUseReflection));
4103                             Writer.Write(", ");
4104                             WriteBooleanValue(member.IsNullable);
4105                             Writer.Write(")");
4106                             WriteSourceEnd(member.ChoiceSource);
4107                             Writer.WriteLine(";");
4108                         }
4109
4110                     }
4111                     else if (typeDesc.IsValueType) {
4112                         Writer.Write(member.Source);
4113                         Writer.Write(" = ");
4114                         Writer.Write(member.ArrayName);
4115                         Writer.WriteLine(";");
4116                     }
4117                 }
4118             }
4119         }
4120
4121         void WriteSourceBeginTyped(string source, TypeDesc typeDesc) {
4122             WriteSourceBegin(source);
4123             if (typeDesc != null && !typeDesc.UseReflection) {
4124                 Writer.Write("(");
4125                 Writer.Write(typeDesc.CSharpName);
4126                 Writer.Write(")");
4127             }
4128         }
4129
4130         void WriteSourceBegin(string source) {
4131             Writer.Write(source);
4132             if (source[source.Length - 1] != '(' && source[source.Length - 1] != '{')
4133                 Writer.Write(" = ");
4134         }
4135         
4136         void WriteSourceEnd(string source) {
4137             // source could be of the form "var", "arrayVar[i]",
4138             // "collection.Add(" or "methodInfo.Invoke(collection, new object[] {"
4139             if (source[source.Length - 1] == '(' )
4140                 Writer.Write(")");
4141             else if( source[source.Length - 1] == '{')
4142                 Writer.Write("})");
4143         }
4144
4145         void WriteArray(string source, string arrayName, ArrayMapping arrayMapping, bool readOnly, bool isNullable, int fixupIndex) {
4146             if (arrayMapping.IsSoap) {
4147                 Writer.Write("object rre = ");
4148                 Writer.Write(fixupIndex >= 0 ? "ReadReferencingElement" : "ReadReferencedElement");
4149                 Writer.Write("(");
4150                 WriteID(arrayMapping.TypeName);
4151                 Writer.Write(", ");
4152                 WriteID(arrayMapping.Namespace);
4153                 if (fixupIndex >= 0) {
4154                     Writer.Write(", ");
4155                     Writer.Write("out fixup.Ids[");
4156                     Writer.Write((fixupIndex).ToString(CultureInfo.InvariantCulture));
4157                     Writer.Write("]");
4158                 }
4159                 Writer.WriteLine(");");
4160
4161                 TypeDesc td = arrayMapping.TypeDesc;
4162                 if (td.IsEnumerable || td.IsCollection) {
4163                     Writer.WriteLine("if (rre != null) {");
4164                     Writer.Indent++;
4165                     WriteAddCollectionFixup(td, readOnly, source, "rre");
4166                     Writer.Indent--;
4167                     Writer.WriteLine("}");
4168                 }
4169                 else {
4170                     Writer.WriteLine("try {");
4171                     Writer.Indent++;
4172                     WriteSourceBeginTyped(source, arrayMapping.TypeDesc);
4173                     Writer.Write("rre");
4174                     WriteSourceEnd(source);
4175                     Writer.WriteLine(";");
4176                     WriteCatchCastException(arrayMapping.TypeDesc, "rre", null);
4177                 }
4178             }
4179             else {
4180                 Writer.WriteLine("if (!ReadNull()) {");
4181                 Writer.Indent++;
4182
4183                 MemberMapping memberMapping = new MemberMapping();
4184                 memberMapping.Elements = arrayMapping.Elements;
4185                 memberMapping.TypeDesc = arrayMapping.TypeDesc;
4186                 memberMapping.ReadOnly = readOnly;
4187                 Member member = new Member(this, source, arrayName, 0, memberMapping, false);
4188                 member.IsNullable = false;//Note, Microsoft: IsNullable is set to false since null condition (xsi:nil) is already handled by 'ReadNull()'
4189
4190                 Member[] members = new Member[] { member };
4191                 WriteMemberBegin(members);
4192
4193                 if (readOnly) {
4194                     Writer.Write("if (((object)(");
4195                     Writer.Write(member.ArrayName);
4196                     Writer.Write(") == null) || ");
4197                 }
4198                 else {
4199                     Writer.Write("if (");
4200                 }
4201                 Writer.WriteLine("(Reader.IsEmptyElement)) {");
4202                 Writer.Indent++;
4203                 Writer.WriteLine("Reader.Skip();");
4204                 Writer.Indent--;
4205                 Writer.WriteLine("}");
4206                 Writer.WriteLine("else {");
4207                 Writer.Indent++;
4208
4209                 Writer.WriteLine("Reader.ReadStartElement();");
4210                 int loopIndex = WriteWhileNotLoopStart();
4211                 Writer.Indent++;
4212
4213                 string unknownNode = "UnknownNode(null, " + ExpectedElements(members) + ");";
4214                 WriteMemberElements(members, unknownNode, unknownNode, null, null, null);
4215                 Writer.WriteLine("Reader.MoveToContent();");
4216
4217                 WriteWhileLoopEnd(loopIndex);
4218                 Writer.Indent--;
4219                 Writer.WriteLine("ReadEndElement();");
4220                 Writer.WriteLine("}");
4221
4222                 WriteMemberEnd(members, false);
4223
4224                 Writer.Indent--;
4225                 Writer.WriteLine("}");
4226                 if (isNullable) {
4227                     Writer.WriteLine("else {");
4228                     Writer.Indent++;
4229                     member.IsNullable = true;
4230                     WriteMemberBegin(members);
4231                     WriteMemberEnd(members);
4232                     Writer.Indent--;
4233                     Writer.WriteLine("}");
4234                 }
4235             }
4236         }
4237         
4238         void WriteElement(string source, string arrayName, string choiceSource, ElementAccessor element, ChoiceIdentifierAccessor choice, string checkSpecified, bool checkForNull, bool readOnly, int fixupIndex, int elementIndex) {
4239             if (checkSpecified != null && checkSpecified.Length > 0) {
4240                 Writer.Write(checkSpecified);
4241                 Writer.WriteLine(" = true;");
4242             }
4243
4244             if (element.Mapping is ArrayMapping) {
4245                 WriteArray(source, arrayName, (ArrayMapping)element.Mapping, readOnly, element.IsNullable, fixupIndex);
4246             }
4247             else if (element.Mapping is NullableMapping) {
4248                 string methodName = ReferenceMapping(element.Mapping);
4249 #if DEBUG
4250                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
4251                 if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, element.Mapping.TypeDesc.Name));
4252 #endif
4253                 WriteSourceBegin(source);
4254                 Writer.Write(methodName);
4255                 Writer.Write("(true)");
4256                 WriteSourceEnd(source);
4257                 Writer.WriteLine(";");
4258             }
4259             else if (!element.Mapping.IsSoap && (element.Mapping is PrimitiveMapping)) {
4260                 if (element.IsNullable) {
4261                     Writer.WriteLine("if (ReadNull()) {");
4262                     Writer.Indent++;
4263                     WriteSourceBegin(source);
4264                     if (element.Mapping.TypeDesc.IsValueType) {
4265                         Writer.Write(RaCodeGen.GetStringForCreateInstance(element.Mapping.TypeDesc.CSharpName, element.Mapping.TypeDesc.UseReflection, false, false));
4266                     }
4267                     else {
4268                         Writer.Write("null");
4269                     }
4270                     WriteSourceEnd(source);
4271                     Writer.WriteLine(";");
4272                     Writer.Indent--;
4273                     Writer.WriteLine("}");
4274                     Writer.Write("else ");
4275                 }
4276                 if (element.Default != null && element.Default != DBNull.Value && element.Mapping.TypeDesc.IsValueType) {
4277                     Writer.WriteLine("if (Reader.IsEmptyElement) {");
4278                     Writer.Indent++;
4279                     Writer.WriteLine("Reader.Skip();");
4280                     Writer.Indent--;
4281                     Writer.WriteLine("}");
4282                     Writer.WriteLine("else {");
4283                 }
4284                 else {
4285                     Writer.WriteLine("{");
4286                 }
4287                 Writer.Indent++;
4288
4289                 WriteSourceBegin(source);
4290                 if (element.Mapping.TypeDesc == QnameTypeDesc)
4291                     Writer.Write("ReadElementQualifiedName()");
4292                 else {
4293                     string readFunc; 
4294                     switch (element.Mapping.TypeDesc.FormatterName) {
4295                     case "ByteArrayBase64":
4296                     case "ByteArrayHex": 
4297                         readFunc = "false";
4298                         break;
4299                     default:              
4300                         readFunc = "Reader.ReadElementString()";
4301                         break;
4302                     }
4303                     WritePrimitive(element.Mapping, readFunc);
4304                 }
4305
4306                 WriteSourceEnd(source);
4307                 Writer.WriteLine(";");
4308                 Writer.Indent--;
4309                 Writer.WriteLine("}");
4310             }
4311             else if (element.Mapping is StructMapping || (element.Mapping.IsSoap && element.Mapping is PrimitiveMapping)) {
4312                 TypeMapping mapping = element.Mapping;
4313                 if (mapping.IsSoap) {
4314                     Writer.Write("object rre = ");
4315                     Writer.Write(fixupIndex >= 0 ? "ReadReferencingElement" : "ReadReferencedElement");
4316                     Writer.Write("(");
4317                     WriteID(mapping.TypeName);
4318                     Writer.Write(", ");
4319                     WriteID(mapping.Namespace);
4320
4321                     if (fixupIndex >= 0) {
4322                         Writer.Write(", out fixup.Ids[");
4323                         Writer.Write((fixupIndex).ToString(CultureInfo.InvariantCulture));
4324                         Writer.Write("]");
4325                     }
4326                     Writer.Write(")");
4327                     WriteSourceEnd(source);
4328                     Writer.WriteLine(";");
4329
4330                     if (mapping.TypeDesc.IsValueType) {
4331                         Writer.WriteLine("if (rre != null) {");
4332                         Writer.Indent++;
4333                     }
4334
4335                     Writer.WriteLine("try {");
4336                     Writer.Indent++;
4337                     WriteSourceBeginTyped(source, mapping.TypeDesc);
4338                     Writer.Write("rre");
4339                     WriteSourceEnd(source);
4340                     Writer.WriteLine(";");
4341                     WriteCatchCastException(mapping.TypeDesc, "rre", null);
4342                     Writer.Write("Referenced(");
4343                     Writer.Write(source);
4344                     Writer.WriteLine(");");
4345                     if (mapping.TypeDesc.IsValueType) {
4346                         Writer.Indent--;
4347                         Writer.WriteLine("}");
4348                     }
4349                 }
4350                 else {
4351                     string methodName = ReferenceMapping(mapping);
4352 #if DEBUG
4353                         // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
4354                         if (methodName == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name));
4355 #endif
4356
4357                     if (checkForNull) {
4358                         Writer.Write("if ((object)(");
4359                         Writer.Write(arrayName);
4360                         Writer.Write(") == null) Reader.Skip(); else ");
4361                     }
4362                     WriteSourceBegin(source);
4363                     Writer.Write(methodName);
4364                     Writer.Write("(");
4365                     if (mapping.TypeDesc.IsNullable) {
4366                         WriteBooleanValue(element.IsNullable);
4367                         Writer.Write(", ");
4368                     }
4369                     Writer.Write("true");
4370                     Writer.Write(")");
4371                     WriteSourceEnd(source);
4372                     Writer.WriteLine(";");
4373                 }
4374             }
4375             else if (element.Mapping is SpecialMapping) {
4376                 SpecialMapping special = (SpecialMapping)element.Mapping;
4377                 switch (special.TypeDesc.Kind) {
4378                 case TypeKind.Node:
4379                     bool isDoc = special.TypeDesc.FullName == typeof(XmlDocument).FullName;
4380                     WriteSourceBeginTyped(source, special.TypeDesc);
4381                     Writer.Write(isDoc ? "ReadXmlDocument(" : "ReadXmlNode(");
4382                     Writer.Write(element.Any ? "false" : "true");
4383                     Writer.Write(")");
4384                     WriteSourceEnd(source);
4385                     Writer.WriteLine(";");
4386                     break;
4387                 case TypeKind.Serializable:
4388                     SerializableMapping sm = (SerializableMapping)element.Mapping;
4389                     // check to see if we need to do the derivation
4390                     if (sm.DerivedMappings != null) {
4391                         Writer.Write(typeof(XmlQualifiedName).FullName);
4392                         Writer.WriteLine(" tser = GetXsiType();");
4393                         Writer.Write("if (tser == null");
4394                         Writer.Write(" || ");
4395                         WriteQNameEqual("tser", sm.XsiType.Name, sm.XsiType.Namespace);
4396
4397                         Writer.WriteLine(") {");
4398                         Writer.Indent++;
4399                     }
4400                     WriteSourceBeginTyped(source, sm.TypeDesc);
4401                     Writer.Write("ReadSerializable(( ");
4402                     Writer.Write(typeof(IXmlSerializable).FullName);
4403                     Writer.Write(")");
4404                     Writer.Write(RaCodeGen.GetStringForCreateInstance(sm.TypeDesc.CSharpName, sm.TypeDesc.UseReflection, sm.TypeDesc.CannotNew, false));
4405                     bool isWrappedAny = !element.Any && IsWildcard(sm);
4406                     if (isWrappedAny) {
4407                         Writer.WriteLine(", true");
4408                     }
4409                     Writer.Write(")");
4410                     WriteSourceEnd(source);
4411                     Writer.WriteLine(";");
4412                     if (sm.DerivedMappings != null) {
4413                         Writer.Indent--;
4414                         Writer.WriteLine("}");
4415                         WriteDerivedSerializable(sm, sm, source, isWrappedAny);
4416                         WriteUnknownNode("UnknownNode", "null", null, true);
4417                     }
4418                     break;
4419                 default:
4420                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
4421                 }
4422             }
4423             else {
4424                 throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
4425             }
4426             if (choice != null) {
4427                 #if DEBUG
4428                     // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
4429                     if (choiceSource == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "need parent for the " + source));
4430                 #endif
4431
4432                 string enumTypeName = choice.Mapping.TypeDesc.CSharpName;
4433                 Writer.Write(choiceSource);
4434                 Writer.Write(" = ");
4435                 CodeIdentifier.CheckValidIdentifier(choice.MemberIds[elementIndex]);
4436                 Writer.Write(RaCodeGen.GetStringForEnumMember(enumTypeName, choice.MemberIds[elementIndex], choice.Mapping.TypeDesc.UseReflection));
4437                 Writer.WriteLine(";");
4438             }
4439         }
4440
4441         void WriteDerivedSerializable(SerializableMapping head, SerializableMapping mapping, string source, bool isWrappedAny) {
4442             if (mapping == null)
4443                 return;
4444             for (SerializableMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
4445                 Writer.Write("else if (tser == null");
4446                 Writer.Write(" || ");
4447                 WriteQNameEqual("tser", derived.XsiType.Name, derived.XsiType.Namespace);
4448
4449                 Writer.WriteLine(") {");
4450                 Writer.Indent++;
4451
4452                 if (derived.Type != null) {
4453                     if (head.Type.IsAssignableFrom(derived.Type)) {
4454                         WriteSourceBeginTyped(source, head.TypeDesc);
4455                         Writer.Write("ReadSerializable(( ");
4456                         Writer.Write(typeof(IXmlSerializable).FullName);
4457                         Writer.Write(")");
4458                         Writer.Write(RaCodeGen.GetStringForCreateInstance(derived.TypeDesc.CSharpName, derived.TypeDesc.UseReflection, derived.TypeDesc.CannotNew, false));
4459                         if (isWrappedAny) {
4460                             Writer.WriteLine(", true");
4461                         }
4462                         Writer.Write(")");
4463                         WriteSourceEnd(source);
4464                         Writer.WriteLine(";");
4465                     }
4466                     else {
4467                         Writer.Write("throw CreateBadDerivationException(");
4468                         WriteQuotedCSharpString(derived.XsiType.Name);
4469                         Writer.Write(", ");
4470                         WriteQuotedCSharpString(derived.XsiType.Namespace);
4471                         Writer.Write(", ");
4472                         WriteQuotedCSharpString(head.XsiType.Name);
4473                             Writer.Write(", ");
4474                         WriteQuotedCSharpString(head.XsiType.Namespace);
4475                         Writer.Write(", ");
4476                         WriteQuotedCSharpString(derived.Type.FullName);
4477                         Writer.Write(", ");
4478                         WriteQuotedCSharpString(head.Type.FullName);
4479                         Writer.WriteLine(");");
4480                     }
4481                 }
4482                 else {
4483                     Writer.WriteLine("// " + "missing real mapping for " + derived.XsiType);
4484                     Writer.Write("throw CreateMissingIXmlSerializableType(");
4485                     WriteQuotedCSharpString(derived.XsiType.Name);
4486                     Writer.Write(", ");
4487                     WriteQuotedCSharpString(derived.XsiType.Namespace);
4488                     Writer.Write(", ");
4489                     WriteQuotedCSharpString(head.Type.FullName);
4490                     Writer.WriteLine(");");
4491                 }
4492
4493                 Writer.Indent--;
4494                 Writer.WriteLine("}");
4495
4496                 WriteDerivedSerializable(head, derived, source, isWrappedAny);
4497             }
4498         }
4499
4500         int WriteWhileNotLoopStart()
4501         {
4502             Writer.WriteLine("Reader.MoveToContent();");
4503             int loopIndex = WriteWhileLoopStartCheck();
4504             Writer.Write("while (Reader.NodeType != ");
4505             Writer.Write(typeof(XmlNodeType).FullName);
4506             Writer.Write(".EndElement && Reader.NodeType != ");
4507             Writer.Write(typeof(XmlNodeType).FullName);
4508             Writer.WriteLine(".None) {");
4509             return loopIndex;
4510         }
4511
4512         void WriteWhileLoopEnd(int loopIndex)
4513         {
4514             WriteWhileLoopEndCheck(loopIndex);
4515             Writer.Indent--;
4516             Writer.WriteLine("}");
4517         }
4518
4519         int WriteWhileLoopStartCheck()
4520         {
4521             Writer.WriteLine(String.Format(CultureInfo.InvariantCulture, "int whileIterations{0} = 0;", nextWhileLoopIndex));
4522             Writer.WriteLine(String.Format(CultureInfo.InvariantCulture, "int readerCount{0} = ReaderCount;", nextWhileLoopIndex));
4523             return nextWhileLoopIndex++;
4524         }
4525
4526         void WriteWhileLoopEndCheck(int loopIndex)
4527         {
4528             Writer.WriteLine(String.Format(CultureInfo.InvariantCulture, "CheckReaderCount(ref whileIterations{0}, ref readerCount{1});", loopIndex, loopIndex));
4529         }
4530
4531         void WriteParamsRead(int length) {
4532             Writer.Write("bool[] paramsRead = new bool[");
4533             Writer.Write(length.ToString(CultureInfo.InvariantCulture));
4534             Writer.WriteLine("];");
4535         }
4536         
4537         void WriteReadNonRoots() {
4538             Writer.WriteLine("Reader.MoveToContent();");
4539             int loopIndex = WriteWhileLoopStartCheck();
4540             Writer.Write("while (Reader.NodeType == ");
4541             Writer.Write(typeof(XmlNodeType).FullName);
4542             Writer.WriteLine(".Element) {");
4543             Writer.Indent++;
4544             Writer.Write("string root = Reader.GetAttribute(\"root\", \"");
4545             Writer.Write(Soap.Encoding);
4546             Writer.WriteLine("\");");
4547             Writer.Write("if (root == null || ");
4548             Writer.Write(typeof(XmlConvert).FullName);
4549             Writer.WriteLine(".ToBoolean(root)) break;");
4550             Writer.WriteLine("ReadReferencedElement();");
4551             Writer.WriteLine("Reader.MoveToContent();");
4552             WriteWhileLoopEnd(loopIndex);
4553         }
4554
4555         void WriteBooleanValue(bool value) {
4556             Writer.Write(value ? "true" : "false");
4557         }
4558
4559         void WriteInitCheckTypeHrefList(string source) {
4560             Writer.Write(typeof(ArrayList).FullName);
4561             Writer.Write(" ");
4562             Writer.Write(source);
4563             Writer.Write(" = new ");
4564             Writer.Write(typeof(ArrayList).FullName);
4565             Writer.WriteLine("();");
4566
4567             Writer.Write(typeof(ArrayList).FullName);
4568             Writer.Write(" ");
4569             Writer.Write(source);
4570             Writer.Write("IsObject = new ");
4571             Writer.Write(typeof(ArrayList).FullName);
4572             Writer.WriteLine("();");
4573         }
4574         
4575         void WriteHandleHrefList(Member[] members, string listSource) {
4576             Writer.WriteLine("int isObjectIndex = 0;");
4577             Writer.Write("foreach (object obj in ");
4578             Writer.Write(listSource);
4579             Writer.WriteLine(") {");
4580             Writer.Indent++;
4581             Writer.WriteLine("bool isReferenced = true;");
4582             Writer.Write("bool isObject = (bool)");
4583             Writer.Write(listSource);
4584             Writer.WriteLine("IsObject[isObjectIndex++];");
4585             Writer.WriteLine("object refObj = isObject ? obj : GetTarget((string)obj);");
4586             Writer.WriteLine("if (refObj == null) continue;");
4587             Writer.Write(typeof(Type).FullName);
4588             Writer.WriteLine(" refObjType = refObj.GetType();");
4589             Writer.WriteLine("string refObjId = null;");
4590
4591             WriteMemberElementsIf(members, null, "isReferenced = false;", "refObj");
4592
4593             Writer.WriteLine("if (isObject && isReferenced) Referenced(refObj); // need to mark this obj as ref'd since we didn't do GetTarget");
4594             Writer.Indent--;
4595             Writer.WriteLine("}");
4596         }
4597
4598         void WriteIfNotSoapRoot(string source) {
4599             Writer.Write("if (Reader.GetAttribute(\"root\", \"");
4600             Writer.Write(Soap.Encoding);
4601             Writer.WriteLine("\") == \"0\") {");
4602             Writer.Indent++;
4603             Writer.WriteLine(source);
4604             Writer.Indent--;
4605             Writer.WriteLine("}");
4606         }
4607
4608         void WriteCreateMapping(TypeMapping mapping, string local) {
4609             string fullTypeName = mapping.TypeDesc.CSharpName;
4610             bool useReflection = mapping.TypeDesc.UseReflection;
4611             bool ctorInaccessible = mapping.TypeDesc.CannotNew;
4612
4613             Writer.Write(useReflection ? "object" : fullTypeName);
4614             Writer.Write(" ");
4615             Writer.Write(local);
4616             Writer.WriteLine(";");
4617
4618             if (ctorInaccessible) {
4619                 Writer.WriteLine("try {");
4620                 Writer.Indent++;
4621             }
4622             Writer.Write(local);
4623             Writer.Write(" = ");
4624             Writer.Write(RaCodeGen.GetStringForCreateInstance(fullTypeName, useReflection, mapping.TypeDesc.CannotNew, true));
4625             Writer.WriteLine(";");
4626             if (ctorInaccessible) {
4627                 WriteCatchException(typeof(MissingMethodException));
4628                 Writer.Indent++;
4629                 Writer.Write("throw CreateInaccessibleConstructorException(");
4630                 WriteQuotedCSharpString(fullTypeName);
4631                 Writer.WriteLine(");");
4632
4633                 WriteCatchException(typeof(SecurityException));
4634                 Writer.Indent++;
4635
4636                 Writer.Write("throw CreateCtorHasSecurityException(");
4637                 WriteQuotedCSharpString(fullTypeName);
4638                 Writer.WriteLine(");");
4639
4640                 Writer.Indent--;
4641                 Writer.WriteLine("}");
4642             }
4643         }
4644
4645         void WriteCatchException(Type exceptionType) {
4646             Writer.Indent--;
4647             Writer.WriteLine("}");
4648             Writer.Write("catch (");
4649             Writer.Write(exceptionType.FullName);
4650             Writer.WriteLine(") {");
4651         }
4652
4653         void WriteCatchCastException(TypeDesc typeDesc, string source, string id) {
4654             WriteCatchException(typeof(InvalidCastException));
4655             Writer.Indent++;
4656             Writer.Write("throw CreateInvalidCastException(");
4657             Writer.Write(RaCodeGen.GetStringForTypeof(typeDesc.CSharpName, typeDesc.UseReflection));
4658             Writer.Write(", ");
4659             Writer.Write(source);
4660             if (id == null)
4661                 Writer.WriteLine(", null);");
4662             else {
4663                 Writer.Write(", (string)");
4664                 Writer.Write(id);
4665                 Writer.WriteLine(");");
4666             }
4667             Writer.Indent--;
4668             Writer.WriteLine("}");
4669         }
4670         void WriteArrayLocalDecl( string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
4671             RaCodeGen.WriteArrayLocalDecl(typeName, variableName, initValue, arrayTypeDesc);
4672         }
4673         void WriteCreateInstance(string escapedName, string source, bool useReflection, bool ctorInaccessible){
4674             RaCodeGen.WriteCreateInstance(escapedName, source, useReflection, ctorInaccessible);
4675         }
4676         void WriteLocalDecl(string typeFullName, string variableName, string initValue, bool useReflection) {
4677             RaCodeGen.WriteLocalDecl(typeFullName, variableName, initValue, useReflection);
4678         }
4679     }
4680 }