New test.
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlReflectionImporter.cs
1 // 
2 // System.Xml.Serialization.XmlReflectionImporter 
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Erik LeBel (eriklebel@yahoo.ca)
7 //   Lluis Sanchez Gual (lluis@ximian.com)
8 //
9 // Copyright (C) Tim Coleman, 2002
10 // (C) 2003 Erik LeBel
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Collections;
35 using System.Globalization;
36 using System.Reflection;
37 using System.Xml.Schema;
38
39 namespace System.Xml.Serialization {
40         public class XmlReflectionImporter {
41
42                 string initialDefaultNamespace;
43                 XmlAttributeOverrides attributeOverrides;
44                 ArrayList includedTypes;
45                 ReflectionHelper helper = new ReflectionHelper();
46                 int arrayChoiceCount = 1;
47                 ArrayList relatedMaps = new ArrayList ();
48                 bool allowPrivateTypes = false;
49
50                 static readonly string errSimple = "Cannot serialize object of type '{0}'. Base " +
51                         "type '{1}' has simpleContent and can be only extended by adding XmlAttribute " +
52                         "elements. Please consider changing XmlText member of the base class to string array";
53
54                 static readonly string errSimple2 = "Cannot serialize object of type '{0}'. " +
55                         "Consider changing type of XmlText member '{1}' from '{2}' to string or string array";
56
57                 #region Constructors
58
59                 public XmlReflectionImporter ()
60                         : this (null, null)
61                 {
62                 }
63
64                 public XmlReflectionImporter (string defaultNamespace)
65                         : this (null, defaultNamespace)
66                 {
67                 }
68
69                 public XmlReflectionImporter (XmlAttributeOverrides attributeOverrides)
70                         : this (attributeOverrides, null)
71                 {
72                 }
73
74                 public XmlReflectionImporter (XmlAttributeOverrides attributeOverrides, string defaultNamespace)
75                 {
76                         if (defaultNamespace == null)
77                                 this.initialDefaultNamespace = String.Empty;
78                         else
79                                 this.initialDefaultNamespace = defaultNamespace;
80
81                         if (attributeOverrides == null)
82                                 this.attributeOverrides = new XmlAttributeOverrides();
83                         else
84                                 this.attributeOverrides = attributeOverrides;
85                 }
86
87 /*              void Reset ()
88                 {
89                         helper = new ReflectionHelper();
90                         arrayChoiceCount = 1;
91                 }
92 */
93                 
94                 internal bool AllowPrivateTypes
95                 {
96                         get { return allowPrivateTypes; }
97                         set { allowPrivateTypes = value; }
98                 }
99
100                 #endregion // Constructors
101
102                 #region Methods
103
104                 public XmlMembersMapping ImportMembersMapping (string elementName,
105                         string ns,
106                         XmlReflectionMember [] members,
107                         bool hasWrapperElement)
108                 {
109                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, true);
110                 }
111
112 #if NET_2_0
113                 [MonoTODO]
114                 public
115 #endif
116                 XmlMembersMapping ImportMembersMapping (string elementName, 
117                         string ns, 
118                         XmlReflectionMember[] members, 
119                         bool hasWrapperElement, 
120                         bool writeAccessors)
121                 {
122                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, true);
123                 }
124
125 #if NET_2_0
126                 [MonoTODO]
127                 public
128 #endif
129                 XmlMembersMapping ImportMembersMapping (string elementName, 
130                         string ns, 
131                         XmlReflectionMember[] members, 
132                         bool hasWrapperElement, 
133                         bool writeAccessors, 
134                         bool validate)
135                 {
136                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, validate, XmlMappingAccess.Read | XmlMappingAccess.Write);
137                 }
138
139 #if NET_2_0
140                 [MonoTODO] // FIXME: handle writeAccessors, validate, and mapping access
141                 public
142 #endif
143                 XmlMembersMapping ImportMembersMapping (string elementName, 
144                         string ns, 
145                         XmlReflectionMember[] members, 
146                         bool hasWrapperElement, 
147                         bool writeAccessors, 
148                         bool validate,
149                         XmlMappingAccess access)
150                 {
151 //                      Reset ();       Disabled. See ChangeLog
152
153                         XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
154                         for (int n=0; n<members.Length; n++)
155                         {
156                                 XmlTypeMapMember mapMem = CreateMapMember (null, members[n], ns);
157                                 mapping[n] = new XmlMemberMapping (members[n].MemberName, ns, mapMem, false);
158                         }
159                         elementName = XmlConvert.EncodeLocalName (elementName);
160                         XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, mapping);
161                         mps.RelatedMaps = relatedMaps;
162                         mps.Format = SerializationFormat.Literal;
163                         Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
164                         mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, extraTypes);
165                         if (allowPrivateTypes) mps.Source.CanBeGenerated = false;
166                         return mps;
167                 }
168
169                 public XmlTypeMapping ImportTypeMapping (Type type)
170                 {
171                         return ImportTypeMapping (type, null, null);
172                 }
173
174                 public XmlTypeMapping ImportTypeMapping (Type type, string defaultNamespace)
175                 {
176                         return ImportTypeMapping (type, null, defaultNamespace);
177                 }
178
179                 public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute group)
180                 {
181                         return ImportTypeMapping (type, group, null);
182                 }
183
184                 public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
185                 {
186                         if (type == null)
187                                 throw new ArgumentNullException ("type");
188
189                         if (type == typeof (void))
190                                 throw new NotSupportedException ("The type " + type.FullName + " may not be serialized.");
191
192                         return ImportTypeMapping (TypeTranslator.GetTypeData (type), root, 
193                                 defaultNamespace);
194                 }
195
196                 internal XmlTypeMapping ImportTypeMapping (TypeData typeData, string defaultNamespace)
197                 {
198                         return ImportTypeMapping (typeData, (XmlRootAttribute) null, 
199                                 defaultNamespace);
200                 }
201
202                 private XmlTypeMapping ImportTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
203                 {
204                         if (typeData == null)
205                                 throw new ArgumentNullException ("typeData");
206
207                         if (typeData.Type == null)
208                                 throw new ArgumentException ("Specified TypeData instance does not have Type set.");
209
210                         if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
211                         if (defaultNamespace == null) defaultNamespace = string.Empty;
212
213                         try {
214                                 XmlTypeMapping map;
215
216                                 switch (typeData.SchemaType) {
217                                         case SchemaTypes.Class: map = ImportClassMapping (typeData, root, defaultNamespace); break;
218                                         case SchemaTypes.Array: map = ImportListMapping (typeData, root, defaultNamespace, null, 0); break;
219                                         case SchemaTypes.XmlNode: map = ImportXmlNodeMapping (typeData, root, defaultNamespace); break;
220                                         case SchemaTypes.Primitive: map = ImportPrimitiveMapping (typeData, root, defaultNamespace); break;
221                                         case SchemaTypes.Enum: map = ImportEnumMapping (typeData, root, defaultNamespace); break;
222                                         case SchemaTypes.XmlSerializable: map = ImportXmlSerializableMapping (typeData, root, defaultNamespace); break;
223                                         default: throw new NotSupportedException ("Type " + typeData.Type.FullName + " not supported for XML stialization");
224                                 }
225
226                                 map.RelatedMaps = relatedMaps;
227                                 map.Format = SerializationFormat.Literal;
228                                 Type[] extraTypes = includedTypes != null ? (Type[]) includedTypes.ToArray (typeof (Type)) : null;
229                                 map.Source = new XmlTypeSerializationSource (typeData.Type, root, attributeOverrides, defaultNamespace, extraTypes);
230                                 if (allowPrivateTypes) map.Source.CanBeGenerated = false;
231                                 return map;
232                         } catch (InvalidOperationException ex) {
233                                 throw new InvalidOperationException (string.Format (CultureInfo.InvariantCulture,
234                                         "There was an error reflecting type '{0}'.", typeData.Type.FullName), ex);
235                         }
236                 }
237
238                 XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
239                 {
240                         string rootNamespace = defaultNamespace;
241                         string typeNamespace = null;
242                         string elementName;
243                         bool includeInSchema = true;
244                         XmlAttributes atts = null;
245                         bool nullable = CanBeNull (typeData);
246
247                         if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
248
249                         if (!typeData.IsListType)
250                         {
251                                 if (attributeOverrides != null) 
252                                         atts = attributeOverrides[typeData.Type];
253
254                                 if (atts != null && typeData.SchemaType == SchemaTypes.Primitive)
255                                         throw new InvalidOperationException ("XmlRoot and XmlType attributes may not be specified for the type " + typeData.FullTypeName);
256                         }
257
258                         if (atts == null) 
259                                 atts = new XmlAttributes (typeData.Type);
260
261                         if (atts.XmlRoot != null && root == null)
262                                 root = atts.XmlRoot;
263
264                         if (atts.XmlType != null)
265                         {
266                                 if (atts.XmlType.Namespace != null && typeData.SchemaType != SchemaTypes.Enum)
267                                         typeNamespace = atts.XmlType.Namespace;
268
269                                 if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
270                                         defaultXmlType = XmlConvert.EncodeLocalName (atts.XmlType.TypeName);
271                                         
272                                 includeInSchema = atts.XmlType.IncludeInSchema;
273                         }
274
275                         elementName = defaultXmlType;
276
277                         if (root != null)
278                         {
279                                 if (root.ElementName.Length != 0)
280                                         elementName = XmlConvert.EncodeLocalName(root.ElementName);
281                                 if (root.Namespace != null)
282                                         rootNamespace = root.Namespace;
283                                 nullable = root.IsNullable;
284                         }
285
286                         if (rootNamespace == null) rootNamespace = "";
287                         if (typeNamespace == null) typeNamespace = rootNamespace;
288                         
289                         XmlTypeMapping map;
290                         switch (typeData.SchemaType) {
291                                 case SchemaTypes.XmlSerializable:
292                                         map = new XmlSerializableMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
293                                         break;
294                                 case SchemaTypes.Primitive:
295                                         if (!typeData.IsXsdType)
296                                                 map = new XmlTypeMapping (elementName, rootNamespace, 
297                                                         typeData, defaultXmlType, XmlSerializer.WsdlTypesNamespace);
298                                         else
299                                                 map = new XmlTypeMapping (elementName, rootNamespace, 
300                                                         typeData, defaultXmlType, typeNamespace);
301                                         break;
302                                 default:
303                                         map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
304                                         break;
305                         }
306
307                         map.IncludeInSchema = includeInSchema;
308                         map.IsNullable = nullable;
309                         relatedMaps.Add (map);
310                         
311                         return map;
312                 }
313
314                 XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
315                 {
316                         TypeData typeData = TypeTranslator.GetTypeData (type);
317                         return ImportClassMapping (typeData, root, defaultNamespace);
318                 }
319
320                 XmlTypeMapping ImportClassMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
321                 {
322                         Type type = typeData.Type;
323
324                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
325                         if (map != null) return map;
326
327                         if (!allowPrivateTypes)
328                                 ReflectionHelper.CheckSerializableType (type, false);
329                         
330                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
331                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
332                         helper.RegisterSchemaType (map, map.XmlType, map.XmlTypeNamespace);
333
334                         // Import members
335
336                         ClassMap classMap = new ClassMap ();
337                         map.ObjectMap = classMap;
338
339                         ICollection members = GetReflectionMembers (type);
340                         foreach (XmlReflectionMember rmember in members)
341                         {
342                                 string ns = map.XmlTypeNamespace;
343                                 if (rmember.XmlAttributes.XmlIgnore) continue;
344                                 if (rmember.DeclaringType != null && rmember.DeclaringType != type) {
345                                         XmlTypeMapping bmap = ImportClassMapping (rmember.DeclaringType, root, defaultNamespace);
346                                         ns = bmap.XmlTypeNamespace;
347                                 }
348
349                                 try {
350                                         XmlTypeMapMember mem = CreateMapMember (type, rmember, ns);
351                                         mem.CheckOptionalValueType (type);
352                                         classMap.AddMember (mem);
353                                 } catch (Exception ex) {
354                                         throw new InvalidOperationException (string.Format (
355                                                 CultureInfo.InvariantCulture, "There was an error" +
356                                                 " reflecting field '{0}'.", rmember.MemberName), ex);
357                                 }
358                         }
359
360                         // Import extra classes
361
362                         if (type == typeof (object) && includedTypes != null)
363                         {
364                                 foreach (Type intype in includedTypes)
365                                         map.DerivedTypes.Add (ImportTypeMapping (intype, defaultNamespace));
366                         }
367
368                         // Register inheritance relations
369
370                         if (type.BaseType != null)
371                         {
372                                 XmlTypeMapping bmap = ImportClassMapping (type.BaseType, root, defaultNamespace);
373                                 ClassMap cbmap = bmap.ObjectMap as ClassMap;
374                                 
375                                 if (type.BaseType != typeof (object)) {
376                                         map.BaseMap = bmap;
377                                         if (!cbmap.HasSimpleContent)
378                                                 classMap.SetCanBeSimpleType (false);
379                                 }
380                                 
381                                 // At this point, derived classes of this map must be already registered
382                                 
383                                 RegisterDerivedMap (bmap, map);
384                                 
385                                 if (cbmap.HasSimpleContent && classMap.ElementMembers != null && classMap.ElementMembers.Count != 1)
386                                         throw new InvalidOperationException (String.Format (errSimple, map.TypeData.TypeName, map.BaseMap.TypeData.TypeName));
387                         }
388                         
389                         ImportIncludedTypes (type, defaultNamespace);
390                         
391                         if (classMap.XmlTextCollector != null && !classMap.HasSimpleContent)
392                         {
393                                 XmlTypeMapMember mem = classMap.XmlTextCollector;
394                                 if (mem.TypeData.Type != typeof(string) && 
395                                    mem.TypeData.Type != typeof(string[]) && 
396                                    mem.TypeData.Type != typeof(object[]) && 
397                                    mem.TypeData.Type != typeof(XmlNode[]))
398                                    
399                                         throw new InvalidOperationException (String.Format (errSimple2, map.TypeData.TypeName, mem.Name, mem.TypeData.TypeName));
400                         }
401                         
402                         return map;
403                 }
404                 
405                 void RegisterDerivedMap (XmlTypeMapping map, XmlTypeMapping derivedMap)
406                 {
407                         map.DerivedTypes.Add (derivedMap);
408                         map.DerivedTypes.AddRange (derivedMap.DerivedTypes);
409                         
410                         if (map.BaseMap != null)
411                                 RegisterDerivedMap (map.BaseMap, derivedMap);
412                         else {
413                                 XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
414                                 if (obmap != map)
415                                         obmap.DerivedTypes.Add (derivedMap);
416                         }
417                 }
418
419                 string GetTypeNamespace (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
420                 {
421                         string typeNamespace = null;
422                         
423                         XmlAttributes atts = null;
424                         if (!typeData.IsListType)
425                         {
426                                 if (attributeOverrides != null)
427                                         atts = attributeOverrides[typeData.Type];
428                         }
429
430                         if (atts == null)
431                                 atts = new XmlAttributes (typeData.Type);
432
433                         if (atts.XmlType != null)
434                         {
435                                 if (atts.XmlType.Namespace != null && atts.XmlType.Namespace.Length != 0 && typeData.SchemaType != SchemaTypes.Enum)
436                                         typeNamespace = atts.XmlType.Namespace;
437                         }
438
439                         if (typeNamespace != null && typeNamespace.Length != 0) return typeNamespace;
440                         
441                         if (atts.XmlRoot != null && root == null)
442                                 root = atts.XmlRoot;
443
444                         if (root != null)
445                         {
446                                 if (root.Namespace != null && root.Namespace.Length != 0)
447                                         return root.Namespace;
448                         }
449
450                         if (defaultNamespace == null) return "";
451                         else return defaultNamespace;
452                 }
453
454                 XmlTypeMapping ImportListMapping (Type type, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
455                 {
456                         TypeData typeData = TypeTranslator.GetTypeData (type);
457                         return ImportListMapping (typeData, root, defaultNamespace, atts, nestingLevel);
458                 }
459
460                 XmlTypeMapping ImportListMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
461                 {
462                         Type type = typeData.Type;
463                         ListMap obmap = new ListMap ();
464
465                         if (!allowPrivateTypes)
466                                 ReflectionHelper.CheckSerializableType (type, true);
467                         
468                         if (atts == null) atts = new XmlAttributes();
469                         Type itemType = typeData.ListItemType;
470
471                         // warning: byte[][] should not be considered multiarray
472                         bool isMultiArray = (type.IsArray && (TypeTranslator.GetTypeData(itemType).SchemaType == SchemaTypes.Array) && itemType.IsArray);
473
474                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
475
476                         foreach (XmlArrayItemAttribute att in atts.XmlArrayItems)
477                         {
478                                 if (att.NestingLevel != nestingLevel) continue;
479                                 Type elemType = (att.Type != null) ? att.Type : itemType;
480                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData(elemType, att.DataType));
481                                 elem.Namespace = att.Namespace != null ? att.Namespace : defaultNamespace;
482                                 if (elem.Namespace == null) elem.Namespace = "";
483                                 elem.Form = att.Form;
484                                 elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData);
485                                 elem.NestingLevel = att.NestingLevel;
486
487                                 if (isMultiArray) {
488                                         elem.MappedType = ImportListMapping (elemType, null, elem.Namespace, atts, nestingLevel + 1);
489                                 } else if (elem.TypeData.IsComplexType) {
490                                         elem.MappedType = ImportTypeMapping (elemType, null, elem.Namespace);
491                                 }
492
493                                 if (att.ElementName.Length != 0) {
494                                         elem.ElementName = XmlConvert.EncodeLocalName (att.ElementName);
495                                 } else if (elem.MappedType != null) {
496                                         elem.ElementName = elem.MappedType.ElementName;
497                                 } else {
498                                         elem.ElementName = TypeTranslator.GetTypeData (elemType).XmlType;
499                                 }
500
501                                 list.Add (elem);
502                         }
503
504                         if (list.Count == 0)
505                         {
506                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData (itemType));
507                                 if (isMultiArray)
508                                         elem.MappedType = ImportListMapping (itemType, null, defaultNamespace, atts, nestingLevel + 1);
509                                 else if (elem.TypeData.IsComplexType)
510                                         elem.MappedType = ImportTypeMapping (itemType, null, defaultNamespace);
511
512                                 if (elem.MappedType != null) {
513                                         elem.ElementName = elem.MappedType.XmlType;
514                                 } else {
515                                         elem.ElementName = TypeTranslator.GetTypeData (itemType).XmlType;
516                                 }
517
518                                 elem.Namespace = (defaultNamespace != null) ? defaultNamespace : "";
519                                 elem.IsNullable = CanBeNull (elem.TypeData);
520                                 list.Add (elem);
521                         }
522
523                         obmap.ItemInfo = list;
524
525                         // If there can be different element names (types) in the array, then its name cannot
526                         // be "ArrayOfXXX" it must be something like ArrayOfChoiceNNN
527
528                         string baseName;
529                         if (list.Count > 1) {
530                                 baseName = "ArrayOfChoice" + (arrayChoiceCount++);
531                         } else {
532                                 XmlTypeMapElementInfo elem = ((XmlTypeMapElementInfo) list[0]);
533                                 if (elem.MappedType != null) {
534                                         baseName = TypeTranslator.GetArrayName (elem.MappedType.XmlType);
535                                 } else {
536                                         baseName = TypeTranslator.GetArrayName (elem.ElementName);
537                                 }
538                         }
539
540                         // Avoid name colisions
541
542                         int nameCount = 1;
543                         string name = baseName;
544
545                         do {
546                                 XmlTypeMapping foundMap = helper.GetRegisteredSchemaType (name, defaultNamespace);
547                                 if (foundMap == null) nameCount = -1;
548                                 else if (obmap.Equals (foundMap.ObjectMap) && typeData.Type == foundMap.TypeData.Type) return foundMap;
549                                 else name = baseName + (nameCount++);
550                         }
551                         while (nameCount != -1);
552
553                         XmlTypeMapping map = CreateTypeMapping (typeData, root, name, defaultNamespace);
554                         map.ObjectMap = obmap;
555                         
556                         // Register any of the including types as a derived class of object
557                         XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
558                         
559                         XmlTypeMapping objectMapping = ImportTypeMapping (typeof(object));
560                         for (int i = 0; i < includes.Length; i++)
561                         {
562                                 Type includedType = includes[i].Type;
563                                 objectMapping.DerivedTypes.Add(ImportTypeMapping (includedType, null, defaultNamespace));
564                         }
565                         
566                         // Register this map as a derived class of object
567
568                         helper.RegisterSchemaType (map, name, defaultNamespace);
569                         ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
570
571                         return map;
572                 }
573
574                 XmlTypeMapping ImportXmlNodeMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
575                 {
576                         Type type = typeData.Type;
577                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
578                         if (map != null) return map;
579
580                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
581                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
582                         
583                         if (type.BaseType != null)
584                         {
585                                 XmlTypeMapping bmap = ImportTypeMapping (type.BaseType, root, defaultNamespace);
586                                 if (type.BaseType != typeof (object))
587                                         map.BaseMap = bmap;
588                                 
589                                 RegisterDerivedMap (bmap, map);
590                         }
591
592                         return map;
593                 }
594
595                 XmlTypeMapping ImportPrimitiveMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
596                 {
597                         Type type = typeData.Type;
598                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
599                         if (map != null) return map;
600                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
601                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
602                         return map;
603                 }
604
605                 XmlTypeMapping ImportEnumMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
606                 {
607                         Type type = typeData.Type;
608                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
609                         if (map != null) return map;
610                         
611                         if (!allowPrivateTypes)
612                                 ReflectionHelper.CheckSerializableType (type, false);
613                                 
614                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
615                         map.IsNullable = false;
616                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
617
618                         string [] names = Enum.GetNames (type);
619                         ArrayList members = new ArrayList();
620                         foreach (string name in names)
621                         {
622                                 FieldInfo field = type.GetField (name);
623                                 string xmlName = null;
624                                 if (field.IsDefined(typeof(XmlIgnoreAttribute), false))
625                                         continue;
626                                 object[] atts = field.GetCustomAttributes (typeof(XmlEnumAttribute), false);
627                                 if (atts.Length > 0) xmlName = ((XmlEnumAttribute)atts[0]).Name;
628                                 if (xmlName == null) xmlName = name;
629                                 long value = ((IConvertible) field.GetValue (null)).ToInt64 (CultureInfo.InvariantCulture);
630                                 members.Add (new EnumMap.EnumMapMember (xmlName, name, value));
631                         }
632
633                         bool isFlags = type.IsDefined (typeof (FlagsAttribute), false);
634                         map.ObjectMap = new EnumMap ((EnumMap.EnumMapMember[])members.ToArray (typeof(EnumMap.EnumMapMember)), isFlags);
635                         ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
636                         return map;
637                 }
638
639                 XmlTypeMapping ImportXmlSerializableMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
640                 {
641                         Type type = typeData.Type;
642                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
643                         if (map != null) return map;
644                         
645                         if (!allowPrivateTypes)
646                                 ReflectionHelper.CheckSerializableType (type, false);
647                                 
648                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
649                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
650                         return map;
651                 }
652
653                 void ImportIncludedTypes (Type type, string defaultNamespace)
654                 {
655                         XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
656                         for (int n=0; n<includes.Length; n++)
657                         {
658                                 Type includedType = includes[n].Type;
659                                 ImportTypeMapping (includedType, null, defaultNamespace);
660                         }
661                 }
662
663                 ICollection GetReflectionMembers (Type type)
664                 {
665                         // First we want to find the inheritance hierarchy in reverse order.
666                         Type currentType = type;
667                         ArrayList typeList = new ArrayList();
668                         typeList.Add(currentType);
669                         while (currentType != typeof(object))
670                         {
671                                 currentType = currentType.BaseType; // Read the base type.
672                                 typeList.Insert(0, currentType); // Insert at 0 to reverse the order.
673                         }
674
675                         // Read all Fields via reflection.
676                         ArrayList fieldList = new ArrayList();
677                         FieldInfo[] tfields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
678 #if TARGET_JVM
679                         // This statement ensures fields are ordered starting from the base type.
680                         for (int ti=0; ti<typeList.Count; ti++) {
681                                 for (int i=0; i<tfields.Length; i++) {
682                                         FieldInfo field = tfields[i];
683                                         if (field.DeclaringType == typeList[ti])
684                                                 fieldList.Add (field);
685                                 }
686                         }
687 #else
688                         currentType = null;
689                         int currentIndex = 0;
690                         foreach (FieldInfo field in tfields)
691                         {
692                                 // This statement ensures fields are ordered starting from the base type.
693                                 if (currentType != field.DeclaringType)
694                                 {
695                                         currentType = field.DeclaringType;
696                                         currentIndex=0;
697                                 }
698                                 fieldList.Insert(currentIndex++, field);
699                         }
700 #endif
701                         // Read all Properties via reflection.
702                         ArrayList propList = new ArrayList();
703                         PropertyInfo[] tprops = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
704 #if TARGET_JVM
705                         // This statement ensures properties are ordered starting from the base type.
706                         for (int ti=0; ti<typeList.Count; ti++) {
707                                 for (int i=0; i<tprops.Length; i++) {
708                                         PropertyInfo prop = tprops[i];
709                                         if (!prop.CanRead) continue;
710                                         if (prop.GetIndexParameters().Length > 0) continue;
711                                         if (prop.DeclaringType == typeList[ti])
712                                                 propList.Add (prop);
713                                 }
714                         }
715 #else
716                         currentType = null;
717                         currentIndex = 0;
718                         foreach (PropertyInfo prop in tprops)
719                         {
720                                 // This statement ensures properties are ordered starting from the base type.
721                                 if (currentType != prop.DeclaringType)
722                                 {
723                                         currentType = prop.DeclaringType;
724                                         currentIndex = 0;
725                                 }
726                                 if (!prop.CanRead) continue;
727                                 if (prop.GetIndexParameters().Length > 0) continue;
728                                 propList.Insert(currentIndex++, prop);
729                         }
730 #endif
731                         ArrayList members = new ArrayList();
732                         int fieldIndex=0;
733                         int propIndex=0;
734                         // We now step through the type hierarchy from the base (object) through
735                         // to the supplied class, as each step outputting all Fields, and then
736                         // all Properties.  This is the exact same ordering as .NET 1.0/1.1.
737                         foreach (Type t in typeList)
738                         {
739                                 // Add any fields matching the current DeclaringType.
740                                 while (fieldIndex < fieldList.Count)
741                                 {
742                                         FieldInfo field = (FieldInfo)fieldList[fieldIndex];
743                                         if (field.DeclaringType==t)
744                                         {
745                                                 fieldIndex++;
746                                                 XmlAttributes atts = attributeOverrides[type, field.Name];
747                                                 if (atts == null) atts = new XmlAttributes (field);
748                                                 if (atts.XmlIgnore) continue;
749                                                 XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
750                                                 member.DeclaringType = field.DeclaringType;
751                                                 members.Add(member);
752                                         }
753                                         else break;
754                                 }
755
756                                 // Add any properties matching the current DeclaringType.
757                                 while (propIndex < propList.Count)
758                                 {
759                                         PropertyInfo prop = (PropertyInfo)propList[propIndex];
760                                         if (prop.DeclaringType==t)
761                                         {
762                                                 propIndex++;
763                                                 XmlAttributes atts = attributeOverrides[type, prop.Name];
764                                                 if (atts == null) atts = new XmlAttributes (prop);
765                                                 if (atts.XmlIgnore) continue;
766                                                 if (!prop.CanWrite && (TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array || prop.PropertyType.IsArray)) continue;
767                                                 XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
768                                                 member.DeclaringType = prop.DeclaringType;
769                                                 members.Add(member);
770                                         }
771                                         else break;
772                                 }
773                         }
774                         return members;         
775                 }
776                 
777                 private XmlTypeMapMember CreateMapMember (Type declaringType, XmlReflectionMember rmember, string defaultNamespace)
778                 {
779                         XmlTypeMapMember mapMember;
780                         XmlAttributes atts = rmember.XmlAttributes;
781                         TypeData typeData = TypeTranslator.GetTypeData (rmember.MemberType);
782
783                         if (atts.XmlAnyAttribute != null)
784                         {
785                                 if ( (rmember.MemberType.FullName == "System.Xml.XmlAttribute[]") ||
786                                          (rmember.MemberType.FullName == "System.Xml.XmlNode[]") )
787                                 {
788                                         mapMember = new XmlTypeMapMemberAnyAttribute();
789                                 }
790                                 else
791                                         throw new InvalidOperationException ("XmlAnyAttributeAttribute can only be applied to members of type XmlAttribute[] or XmlNode[]");
792                         }
793                         else if (atts.XmlAnyElements != null && atts.XmlAnyElements.Count > 0)
794                         {
795                                 if ( (rmember.MemberType.FullName == "System.Xml.XmlElement[]") ||
796                                          (rmember.MemberType.FullName == "System.Xml.XmlNode[]") ||
797                                          (rmember.MemberType.FullName == "System.Xml.XmlElement"))
798                                 {
799                                         XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
800                                         member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
801                                         mapMember = member;
802                                 }
803                                 else
804                                         throw new InvalidOperationException ("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]");
805                         }
806                         else if (atts.Xmlns)
807                         {
808                                 XmlTypeMapMemberNamespaces mapNamespaces = new XmlTypeMapMemberNamespaces ();
809                                 mapMember = mapNamespaces;
810                         }
811                         else if (atts.XmlAttribute != null)
812                         {
813                                 // An attribute
814
815                                 if (atts.XmlElements != null && atts.XmlElements.Count > 0)
816                                         throw new Exception ("XmlAttributeAttribute and XmlElementAttribute cannot be applied to the same member");
817
818                                 XmlTypeMapMemberAttribute mapAttribute = new XmlTypeMapMemberAttribute ();
819                                 if (atts.XmlAttribute.AttributeName.Length == 0) 
820                                         mapAttribute.AttributeName = rmember.MemberName;
821                                 else 
822                                         mapAttribute.AttributeName = atts.XmlAttribute.AttributeName;
823
824                                 mapAttribute.AttributeName = XmlConvert.EncodeLocalName (mapAttribute.AttributeName);
825
826                                 if (typeData.IsComplexType)
827                                         mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
828                                 
829                                 if (atts.XmlAttribute.Namespace != null && atts.XmlAttribute.Namespace != defaultNamespace)
830                                 {
831                                         if (atts.XmlAttribute.Form == XmlSchemaForm.Unqualified)
832                                                 throw new InvalidOperationException ("The Form property may not be 'Unqualified' when an explicit Namespace property is present");
833                                         mapAttribute.Form = XmlSchemaForm.Qualified;
834                                         mapAttribute.Namespace = atts.XmlAttribute.Namespace;
835                                 }
836                                 else
837                                 {
838                                         mapAttribute.Form = atts.XmlAttribute.Form;
839                                         if (atts.XmlAttribute.Form == XmlSchemaForm.Qualified)
840                                                 mapAttribute.Namespace = defaultNamespace;
841                                         else
842                                                 mapAttribute.Namespace = "";
843                                 }
844                                 
845                                 typeData = TypeTranslator.GetTypeData(rmember.MemberType, atts.XmlAttribute.DataType);
846                                 mapMember = mapAttribute;
847                         }
848                         else if (typeData.SchemaType == SchemaTypes.Array)
849                         {
850                                 // If the member has a single XmlElementAttribute and the type is the type of the member,
851                                 // then it is not a flat list
852                                 
853                                 if (atts.XmlElements.Count > 1 ||
854                                    (atts.XmlElements.Count == 1 && atts.XmlElements[0].Type != typeData.Type) ||
855                                    (atts.XmlText != null))
856                                 {
857                                         // A flat list
858
859                                         // TODO: check that it does not have XmlArrayAttribute
860                                         XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
861                                         member.ListMap = new ListMap ();
862                                         member.ListMap.ItemInfo = ImportElementInfo (declaringType, XmlConvert.EncodeLocalName (rmember.MemberName), defaultNamespace, typeData.ListItemType, member, atts);
863                                         member.ElementInfo = member.ListMap.ItemInfo;
864                                         member.ListMap.ChoiceMember = member.ChoiceMember;
865                                         mapMember = member;
866                                 }
867                                 else
868                                 {
869                                         // A list
870
871                                         XmlTypeMapMemberList member = new XmlTypeMapMemberList ();
872
873                                         // Creates an ElementInfo that identifies the array instance. 
874                                         member.ElementInfo = new XmlTypeMapElementInfoList();
875                                         XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, typeData);
876                                         elem.ElementName = XmlConvert.EncodeLocalName((atts.XmlArray != null && atts.XmlArray.ElementName.Length != 0) ? atts.XmlArray.ElementName : rmember.MemberName);
877                                         elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
878                                         elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
879                                         elem.IsNullable = (atts.XmlArray != null) ? atts.XmlArray.IsNullable : false;
880                                         elem.Form = (atts.XmlArray != null) ? atts.XmlArray.Form : XmlSchemaForm.Qualified;
881
882                                         member.ElementInfo.Add (elem);
883                                         mapMember = member;
884                                 }
885                         }
886                         else
887                         {
888                                 // An element
889
890                                 XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
891                                 member.ElementInfo = ImportElementInfo (declaringType, XmlConvert.EncodeLocalName(rmember.MemberName), defaultNamespace, rmember.MemberType, member, atts);
892                                 mapMember = member;
893                         }
894
895                         mapMember.DefaultValue = GetDefaultValue (typeData, atts.XmlDefaultValue);
896                         mapMember.TypeData = typeData;
897                         mapMember.Name = rmember.MemberName;
898                         mapMember.IsReturnValue = rmember.IsReturnValue;
899                         return mapMember;
900                 }
901
902                 XmlTypeMapElementInfoList ImportElementInfo (Type cls, string defaultName, string defaultNamespace, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
903                 {
904                         EnumMap choiceEnumMap = null;
905                         Type choiceEnumType = null;
906                         
907                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
908                         ImportTextElementInfo (list, defaultType, member, atts);
909                         
910                         if (atts.XmlChoiceIdentifier != null) {
911                                 if (cls == null)
912                                         throw new InvalidOperationException ("XmlChoiceIdentifierAttribute not supported in this context.");
913                                         
914                                 member.ChoiceMember = atts.XmlChoiceIdentifier.MemberName;
915                                 MemberInfo[] mems = cls.GetMember (member.ChoiceMember, BindingFlags.Instance|BindingFlags.Public);
916                                 
917                                 if (mems.Length == 0)
918                                         throw new InvalidOperationException ("Choice member '" + member.ChoiceMember + "' not found in class '" + cls);
919                                         
920                                 if (mems[0] is PropertyInfo) {
921                                         PropertyInfo pi = (PropertyInfo)mems[0];
922                                         if (!pi.CanWrite || !pi.CanRead)
923                                                 throw new InvalidOperationException ("Choice property '" + member.ChoiceMember + "' must be read/write.");
924                                         choiceEnumType = pi.PropertyType;
925                                 }
926                                 else choiceEnumType = ((FieldInfo)mems[0]).FieldType;
927                                 
928                                 member.ChoiceTypeData = TypeTranslator.GetTypeData (choiceEnumType);
929                                 
930                                 if (choiceEnumType.IsArray)
931                                         choiceEnumType = choiceEnumType.GetElementType ();
932                                 
933                                 choiceEnumMap = ImportTypeMapping (choiceEnumType).ObjectMap as EnumMap;
934                                 if (choiceEnumMap == null)
935                                         throw new InvalidOperationException ("The member '" + mems[0].Name + "' is not a valid target for XmlChoiceIdentifierAttribute.");
936                         }
937                         
938                         if (atts.XmlElements.Count == 0 && list.Count == 0)
939                         {
940                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType));
941                                 elem.ElementName = defaultName;
942                                 elem.Namespace = defaultNamespace;
943                                 if (elem.TypeData.IsComplexType)
944                                         elem.MappedType = ImportTypeMapping (defaultType, null, defaultNamespace);
945                                 list.Add (elem);
946                         }
947
948                         bool multiType = (atts.XmlElements.Count > 1);
949                         foreach (XmlElementAttribute att in atts.XmlElements)
950                         {
951                                 Type elemType = (att.Type != null) ? att.Type : defaultType;
952                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(elemType, att.DataType));
953                                 elem.Form = att.Form;
954                                 if (elem.Form != XmlSchemaForm.Unqualified)
955                                         elem.Namespace = (att.Namespace != null) ? att.Namespace : defaultNamespace;
956                                 elem.IsNullable = att.IsNullable;
957
958                                 if (elem.IsNullable && !elem.TypeData.IsNullable)
959                                         throw new InvalidOperationException ("IsNullable may not be 'true' for value type " + elem.TypeData.FullTypeName + " in member '" + defaultName + "'");
960                                         
961                                 if (elem.TypeData.IsComplexType)
962                                 {
963                                         if (att.DataType.Length != 0) throw new InvalidOperationException (
964                                                 string.Format(CultureInfo.InvariantCulture, "'{0}' is "
965                                                         + "an invalid value for '{1}.{2}' of type '{3}'. "
966                                                         + "The property may only be specified for primitive types.",
967                                                         att.DataType, cls.FullName, defaultName, 
968                                                         elem.TypeData.FullTypeName));
969                                         elem.MappedType = ImportTypeMapping (elemType, null, elem.Namespace);
970                                 }
971
972                                 if (att.ElementName.Length != 0)  {
973                                         elem.ElementName = XmlConvert.EncodeLocalName(att.ElementName);
974                                 } else if (multiType) {
975                                         if (elem.MappedType != null) {
976                                                 elem.ElementName = elem.MappedType.ElementName;
977                                         } else {
978                                                 elem.ElementName = TypeTranslator.GetTypeData (elemType).XmlType;
979                                         }
980                                 } else {
981                                         elem.ElementName = defaultName;
982                                 }
983
984                                 if (choiceEnumMap != null) {
985                                         string cname = choiceEnumMap.GetEnumName (choiceEnumType.FullName, elem.ElementName);
986                                         if (cname == null)
987                                                 throw new InvalidOperationException (string.Format (
988                                                         CultureInfo.InvariantCulture, "Type {0} is missing"
989                                                         + " enumeration value '{1}' for element '{1} from"
990                                                         + " namespace '{2}'.", choiceEnumType, elem.ElementName,
991                                                         elem.Namespace));
992                                         elem.ChoiceValue = Enum.Parse (choiceEnumType, cname);
993                                 }
994                                         
995                                 list.Add (elem);
996                         }
997                         return list;
998                 }
999
1000                 XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlReflectionMember rmember, XmlTypeMapMemberElement member, XmlAttributes atts)
1001                 {
1002                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
1003
1004                         ImportTextElementInfo (list, rmember.MemberType, member, atts);
1005
1006                         foreach (XmlAnyElementAttribute att in atts.XmlAnyElements)
1007                         {
1008                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
1009                                 if (att.Name.Length != 0) 
1010                                 {
1011                                         elem.ElementName = XmlConvert.EncodeLocalName(att.Name);
1012                                         elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
1013                                 }
1014                                 else 
1015                                 {
1016                                         elem.IsUnnamedAnyElement = true;
1017                                         elem.Namespace = defaultNamespace;
1018                                         if (att.Namespace != null) 
1019                                                 throw new InvalidOperationException ("The element " + rmember.MemberName + " has been attributed with an XmlAnyElementAttribute and a namespace '" + att.Namespace + "', but no name. When a namespace is supplied, a name is also required. Supply a name or remove the namespace.");
1020                                 }
1021                                 list.Add (elem);
1022                         }
1023                         return list;
1024                 }
1025
1026                 void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
1027                 {
1028                         if (atts.XmlText != null)
1029                         {
1030                                 member.IsXmlTextCollector = true;
1031                                 if (atts.XmlText.Type != null) {
1032                                         TypeData td = TypeTranslator.GetTypeData (defaultType);
1033                                         if ((td.SchemaType == SchemaTypes.Primitive || td.SchemaType == SchemaTypes.Enum) && atts.XmlText.Type != defaultType) {
1034                                                 throw new InvalidOperationException ("The type for XmlText may not be specified for primitive types.");
1035                                         }
1036                                         defaultType = atts.XmlText.Type;
1037                                 }
1038                                 if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText);      // Nodes must be text nodes
1039
1040                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
1041
1042                                 if (elem.TypeData.SchemaType != SchemaTypes.Primitive &&
1043                                         elem.TypeData.SchemaType != SchemaTypes.Enum &&
1044                                     elem.TypeData.SchemaType != SchemaTypes.XmlNode &&
1045                                     !(elem.TypeData.SchemaType == SchemaTypes.Array && elem.TypeData.ListItemTypeData.SchemaType == SchemaTypes.XmlNode)
1046                                  )
1047                                         throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
1048
1049                                 elem.IsTextElement = true;
1050                                 elem.WrappedElement = false;
1051                                 list.Add (elem);
1052                         }
1053                 }
1054                 
1055                 bool CanBeNull (TypeData type)
1056                 {
1057 #if !NET_2_0    // idiotic compatibility
1058                         if (type.Type == typeof (XmlQualifiedName))
1059                                 return false;
1060 #endif
1061                         return !type.Type.IsValueType;
1062                 }
1063                 
1064                 public void IncludeType (Type type)
1065                 {
1066                         if (type == null)
1067                                 throw new ArgumentNullException ("type");
1068
1069                         if (includedTypes == null) includedTypes = new ArrayList ();
1070                         if (!includedTypes.Contains (type))
1071                                 includedTypes.Add (type);
1072                         
1073                         if (relatedMaps.Count > 0) {
1074                                 foreach (XmlTypeMapping map in (ArrayList) relatedMaps.Clone ()) {
1075                                         if (map.TypeData.Type == typeof(object))
1076                                                 map.DerivedTypes.Add (ImportTypeMapping (type));
1077                                 }
1078                         }
1079                 }
1080
1081                 public void IncludeTypes (ICustomAttributeProvider provider)
1082                 { 
1083                         object[] ats = provider.GetCustomAttributes (typeof(XmlIncludeAttribute), true);
1084                         
1085                         foreach (XmlIncludeAttribute at in ats)
1086                                 IncludeType (at.Type);
1087                 }
1088
1089                 private object GetDefaultValue (TypeData typeData, object defaultValue)
1090                 {
1091                         if (defaultValue == DBNull.Value || typeData.SchemaType != SchemaTypes.Enum)
1092                                 return defaultValue;
1093
1094                         // get string representation of enum value
1095                         string namedValue = Enum.Format (typeData.Type, defaultValue, "g");
1096                         // get decimal representation of enum value
1097                         string decimalValue = Enum.Format (typeData.Type, defaultValue, "d");
1098
1099                         // if decimal representation matches string representation, then
1100                         // the value is not defined in the enum type (as the "g" format
1101                         // will return the decimal equivalent of the value if the value
1102                         // is not equal to a combination of named enumerated constants
1103                         if (namedValue == decimalValue) {
1104                                 string msg = string.Format (CultureInfo.InvariantCulture,
1105                                         "Value '{0}' cannot be converted to {1}.", defaultValue,
1106                                         defaultValue.GetType ().FullName);
1107                                 throw new InvalidOperationException (msg);
1108                         }
1109
1110                         // XmlSerializer expects integral enum value
1111                         //return namedValue.Replace (',', ' ');
1112                         return defaultValue;
1113                 }
1114
1115                 #endregion // Methods
1116         }
1117 }