2 // Mono Class Libraries
3 // System.Xml.Serialization.XmlSerializer
6 // John Donagher (john@webmeta.com)
7 // Ajay kumar Dwivedi (adwiv@yahoo.com)
8 // Tim Coleman (tim@timcoleman.com)
10 // (C) 2002 John Donagher, Ajay kumar Dwivedi
11 // Copyright (C) Tim Coleman, 2002
15 using System.Collections;
17 using System.Reflection;
19 using System.Xml.Schema;
21 namespace System.Xml.Serialization {
23 /// Summary description for XmlSerializer.
25 public class XmlSerializer {
30 XmlAttributeOverrides overrides;
32 XmlRootAttribute rootAttribute;
33 string defaultNamespace;
34 static Hashtable typeTable;
42 protected XmlSerializer ()
46 public XmlSerializer (Type type)
47 : this (type, null, null, null, null)
52 public XmlSerializer (XmlTypeMapping xmltypemapping)
56 public XmlSerializer (Type type, string defaultNamespace)
57 : this (type, null, null, null, defaultNamespace)
61 public XmlSerializer (Type type, Type[] extraTypes)
62 : this (type, null, extraTypes, null, null)
66 public XmlSerializer (Type type, XmlAttributeOverrides overrides)
67 : this (type, overrides, null, null, null)
71 public XmlSerializer (Type type, XmlRootAttribute root)
72 : this (type, null, null, root, null)
76 internal XmlSerializer (Hashtable typeTable)
78 typeTable = typeTable;
81 public XmlSerializer (Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace)
84 throw new ArgumentNullException ("type", "XmlSerializer can't be constructed with a null type");
87 this.overrides = overrides;
88 this.extraTypes = (extraTypes == null ? new Type[0] : extraTypes);
91 this.rootAttribute = root;
93 object[] attributes = type.GetCustomAttributes (typeof (XmlRootAttribute), false);
94 if (attributes.Length > 0)
95 this.rootAttribute = (XmlRootAttribute) attributes[0];
98 this.defaultNamespace = defaultNamespace;
100 if (typeTable == null)
101 typeTable = new Hashtable ();
103 FillTypeTable (type);
106 #endregion // Constructors
111 public event XmlAttributeEventHandler UnknownAttribute;
113 public event XmlElementEventHandler UnknownElement;
115 public event XmlNodeEventHandler UnknownNode;
117 public event UnreferencedObjectEventHandler UnreferencedObject;
123 public bool UseOrder {
124 get { return useOrder; }
125 set { useOrder = value; }
128 #endregion // Properties
133 public virtual bool CanDeserialize (XmlReader xmlReader)
135 throw new NotImplementedException ();
138 public object Deserialize (Stream stream)
140 throw new NotImplementedException ();
143 public object Deserialize (TextReader textReader)
145 throw new NotImplementedException ();
148 public object Deserialize (XmlReader xmlReader)
150 throw new NotImplementedException ();
153 public void Serialize (Stream stream, object o)
155 XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
156 xmlWriter.Formatting = Formatting.Indented;
157 Serialize (xmlWriter, o, null);
160 public void Serialize (TextWriter textWriter, object o)
162 XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
163 xmlWriter.Formatting = Formatting.Indented;
164 Serialize (xmlWriter, o, null);
167 public void Serialize (XmlWriter xmlWriter, object o)
169 Serialize (xmlWriter, o);
172 public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
174 XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
175 xmlWriter.Formatting = Formatting.Indented;
176 Serialize (xmlWriter, o, namespaces);
179 public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
181 XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
182 xmlWriter.Formatting = Formatting.Indented;
183 Serialize (xmlWriter, o, namespaces);
186 public void Serialize (XmlWriter writer, object o, XmlSerializerNamespaces namespaces)
188 Type objType = o.GetType ();
189 string rootName = objType.Name;
190 string rootNs = String.Empty;
191 string rootPrefix = String.Empty;
193 if (namespaces == null)
194 namespaces = new XmlSerializerNamespaces ();
196 if (namespaces.Count == 0) {
197 namespaces.Add ("xsd", XmlSchema.Namespace);
198 namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
201 XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();
202 XmlQualifiedName[] qnames;
204 writer.WriteStartDocument ();
206 object[] memberObj = (object[]) typeTable[objType];
207 if (memberObj == null)
208 throw new Exception ("Unknown Type " + objType + " encountered during Serialization");
210 Hashtable memberTable = (Hashtable) memberObj[0];
211 XmlAttributes xmlAttributes = (XmlAttributes) memberTable[""];
213 //If we have been passed an XmlRoot, set it on the base class
214 if (rootAttribute != null)
215 xmlAttributes.XmlRoot = rootAttribute;
217 if (xmlAttributes.XmlRoot != null) {
218 isNullable = xmlAttributes.XmlRoot.IsNullable;
219 if (xmlAttributes.XmlRoot.ElementName != null)
220 rootName = xmlAttributes.XmlRoot.ElementName;
221 rootNs = xmlAttributes.XmlRoot.Namespace;
224 if (namespaces.GetPrefix (rootNs) != null)
225 rootPrefix = namespaces.GetPrefix (rootNs);
227 //XMLNS attributes in the Root
228 XmlAttributes XnsAttrs = (XmlAttributes) ((object[]) typeTable[objType])[1];
229 if (XnsAttrs != null) {
230 MemberInfo member = XnsAttrs.MemberInfo;
231 FieldInfo fieldInfo = member as FieldInfo;
232 PropertyInfo propertyInfo = member as PropertyInfo;
233 XmlSerializerNamespaces xns;
235 if (fieldInfo != null)
236 xns = (XmlSerializerNamespaces) fieldInfo.GetValue (o);
238 xns = (XmlSerializerNamespaces) propertyInfo.GetValue (o, null);
240 qnames = xns.ToArray ();
242 foreach (XmlQualifiedName qname in qnames)
243 nss.Add (qname.Name, qname.Namespace);
246 //XmlNs from the namespaces passed
247 qnames = namespaces.ToArray ();
248 foreach (XmlQualifiedName qname in qnames)
249 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
250 nss.Add (qname.Name, qname.Namespace);
252 writer.WriteStartElement (rootPrefix, rootName, rootNs);
254 qnames = nss.ToArray();
255 foreach (XmlQualifiedName qname in qnames)
256 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
257 writer.WriteAttributeString ("xmlns", qname.Name, null, qname.Namespace);
259 if (rootPrefix == String.Empty && rootNs != String.Empty && rootNs != null)
260 writer.WriteAttributeString (String.Empty, "xmlns", null, rootNs);
262 SerializeMembers (writer, o, true);//, namespaces);
263 writer.WriteEndDocument ();
266 private void SerializeMembers (XmlWriter writer, object o, bool isRoot)
268 Type objType = o.GetType ();
269 XmlAttributes nsAttributes = (XmlAttributes) ((object[]) typeTable [objType])[1];
270 ArrayList attributes = (ArrayList) ((object[]) typeTable [objType])[2];
271 ArrayList elements = (ArrayList) ((object[]) typeTable [objType])[3];
274 if (!isRoot && nsAttributes != null) {
275 MemberInfo member = nsAttributes.MemberInfo;
276 FieldInfo fieldInfo = member as FieldInfo;
277 PropertyInfo propertyInfo = member as PropertyInfo;
279 XmlSerializerNamespaces xns;
281 if (fieldInfo != null)
282 xns = (XmlSerializerNamespaces) fieldInfo.GetValue (o);
284 xns = (XmlSerializerNamespaces) propertyInfo.GetValue (o, null);
286 XmlQualifiedName[] qnames = xns.ToArray ();
287 foreach (XmlQualifiedName qname in qnames)
288 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
289 writer.WriteAttributeString ("xmlns", qname.Name, null, qname.Namespace);
292 //Serialize the Attributes.
293 foreach (XmlAttributes xmlAttributes in attributes) {
294 MemberInfo member = xmlAttributes.MemberInfo;
295 FieldInfo fieldInfo = member as FieldInfo;
296 PropertyInfo propertyInfo = member as PropertyInfo;
299 object attributeValue;
300 string attributeValueString;
301 string attributeName;
304 if (fieldInfo != null) {
305 attributeType = fieldInfo.FieldType;
306 attributeValue = fieldInfo.GetValue (o);
309 attributeType = propertyInfo.PropertyType;
310 attributeValue = propertyInfo.GetValue (o, null);
313 attributeName = xmlAttributes.GetAttributeName (attributeType, member.Name);
314 attributeNs = xmlAttributes.GetAttributeNamespace (attributeType);
316 if (attributeValue is XmlQualifiedName) {
317 XmlQualifiedName qname = (XmlQualifiedName) attributeValue;
322 writer.WriteStartAttribute (attributeName, attributeNs);
323 writer.WriteQualifiedName (qname.Name, qname.Namespace);
324 writer.WriteEndAttribute ();
327 else if (attributeValue is XmlQualifiedName[]) {
328 XmlQualifiedName[] qnames = (XmlQualifiedName[]) attributeValue;
329 writer.WriteStartAttribute (attributeName, attributeNs);
331 foreach (XmlQualifiedName qname in qnames) {
335 writer.WriteWhitespace (" ");
336 writer.WriteQualifiedName (qname.Name, qname.Namespace);
338 writer.WriteEndAttribute ();
341 else if (attributeValue is XmlAttribute[]) {
342 XmlAttribute[] xmlattrs = (XmlAttribute[]) attributeValue;
343 foreach (XmlAttribute xmlattr in xmlattrs)
344 xmlattr.WriteTo(writer);
348 attributeValueString = GetXmlValue (attributeValue);
349 if (attributeValueString != GetXmlValue (xmlAttributes.XmlDefaultValue))
350 writer.WriteAttributeString (attributeName, attributeNs, attributeValueString);
353 // Serialize Elements
354 foreach (XmlAttributes xmlElements in elements) {
355 MemberInfo member = xmlElements.MemberInfo;
356 FieldInfo fieldInfo = member as FieldInfo;
357 PropertyInfo propertyInfo = member as PropertyInfo;
364 if (fieldInfo != null) {
365 elementType = fieldInfo.FieldType;
366 elementValue = fieldInfo.GetValue (o);
369 elementType = propertyInfo.PropertyType;
370 elementValue = propertyInfo.GetValue (o, null);
373 elementName = xmlElements.GetElementName (elementType, member.Name);
374 elementNs = xmlElements.GetElementNamespace (elementType);
375 WriteElement (writer, xmlElements, elementName, elementNs, elementType, elementValue);
379 [MonoTODO ("Remove FIXMEs")]
380 private void WriteElement (XmlWriter writer, XmlAttributes attrs, string name, string ns, Type type, Object value)
382 if (IsInbuiltType (type)) {
383 string xmlValue = GetXmlValue (value);
384 if (xmlValue != String.Empty && xmlValue != null)
385 writer.WriteElementString (name, ns, xmlValue);
387 else if (attrs.XmlText != null && value != null) {
388 if (type == typeof (object[])) {
391 else if (type == typeof (string[])) {
394 else if (type == typeof (XmlNode)) {
395 ((XmlNode) value).WriteTo (writer);
397 else if (type == typeof (XmlNode[])) {
398 XmlNode[] nodes = (XmlNode[]) value;
399 foreach (XmlNode node in nodes)
400 node.WriteTo (writer);
403 else if (type.IsArray && value != null) {
404 writer.WriteStartElement (name, ns);
405 SerializeArray (writer, value);
406 writer.WriteEndElement ();
408 else if (value is ICollection) {
409 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
411 //Find a non indexer Count Property with return type of int
412 PropertyInfo countInfo = type.GetProperty ("Count", flags, null, typeof (int), new Type[0], null);
413 PropertyInfo itemInfo = type.GetProperty ("Item", flags, null, null, new Type[1] {typeof (int)}, null);
414 int count = (int) countInfo.GetValue (value, null);
417 for (int i = 0; i < count; i++) {
418 object itemValue = itemInfo.GetValue (value, new object[1] {i});
420 if (itemValue != null) {
421 string itemName = attrs.GetElementName (itemValue.GetType (), name);
422 string itemNs = attrs.GetElementNamespace (itemValue.GetType ());
424 writer.WriteStartElement (itemName, itemNs);
425 SerializeMembers (writer, itemValue, false);
426 writer.WriteEndElement ();
430 else if (value is IEnumerable) {
433 else if (type.IsEnum) {
436 else if (value != null) { //Complex Type?
437 string itemName = attrs.GetElementName (value.GetType (), name);
438 string itemNs = attrs.GetElementNamespace (value.GetType ());
439 writer.WriteStartElement (itemName, itemNs);
440 SerializeMembers (writer, value, false);
441 writer.WriteEndElement ();
449 private void SerializeArray (XmlWriter writer, object o)
451 throw new NotImplementedException ();
455 /// If the type is a string, valuetype or primitive type we do not populate the TypeTable.
456 /// If the type is an array, we populate the TypeTable with Element type of the array.
457 /// If the type implements ICollection, it is handled differently. We do not care for its members.
458 /// If the type implements IEnumberable, we check that it implements Add(). Don't care for members.
460 [MonoTODO ("Remove FIXMEs")]
461 private void FillTypeTable (Type type)
463 if (typeTable.Contains (type))
466 //For value types and strings we don't need the members.
467 //FIXME: We will need the enum types probably.
468 if (IsInbuiltType (type))
471 //Array, ICollection and IEnumberable are treated differenty
473 FillArrayType (type);
476 else if (type.IsEnum) {
481 //There must be a public constructor
482 if (!HasDefaultConstructor (type))
483 throw new Exception ("Can't Serialize Type " + type.Name + " since it does not have default Constructor");
485 if (type.GetInterface ("ICollection") == typeof (System.Collections.ICollection)) {
486 FillICollectionType (type);
489 if (type.GetInterface ("IEnumerable") == typeof (System.Collections.IEnumerable)) {
490 //FillIEnumerableType(type);
496 //Add the Class to the hashtable.
497 //Each value of the hashtable has two objects, one is the hashtable with key of membername (for deserialization)
498 //Other is an Array of XmlSerializernames, Array of XmlAttributes & Array of XmlElements.
499 Object[] memberObj = new Object[4];
500 typeTable.Add (type,memberObj);
502 Hashtable memberTable = new Hashtable ();
503 memberObj[0] = memberTable;
504 memberTable.Add ("", XmlAttributes.FromClass (type));
508 ArrayList attributes = new ArrayList ();
509 memberObj[2] = attributes;
511 ArrayList elements = new ArrayList ();
512 memberObj[3] = elements;
514 //Get the graph of the members. Graph is nothing but the order
515 //in which MS implementation serializes the members.
516 MemberInfo[] minfo = GetGraph (type);
518 foreach (MemberInfo member in minfo) {
519 FieldInfo fieldInfo = (member as FieldInfo);
520 PropertyInfo propertyInfo = (member as PropertyInfo);
522 if (fieldInfo != null) {
523 //If field is readOnly or const, do not serialize it.
524 if (fieldInfo.IsLiteral || fieldInfo.IsInitOnly)
527 XmlAttributes xmlAttributes = XmlAttributes.FromField (member, fieldInfo);
529 //If XmlAttributes have XmlIgnore, ignore this member
531 if (xmlAttributes.XmlIgnore)
534 //If this member is a XmlNs type, set the XmlNs object.
535 if (xmlAttributes.Xmlns) {
536 memberObj[1] = xmlAttributes;
540 //If the member is a attribute Type, Add to attribute list
541 if (xmlAttributes.isAttribute)
542 attributes.Add (xmlAttributes);
543 else //Add to elements
544 elements.Add (xmlAttributes);
546 //Add in the Hashtable.
547 memberTable.Add (member.Name, xmlAttributes);
549 if (xmlAttributes.XmlAnyAttribute != null || xmlAttributes.XmlText != null)
552 if (xmlAttributes.XmlElements.Count > 0) {
553 foreach (XmlElementAttribute elem in xmlAttributes.XmlElements) {
554 if (elem.Type != null)
555 FillTypeTable (elem.Type);
557 FillTypeTable (fieldInfo.FieldType);
562 if (!IsInbuiltType (fieldInfo.FieldType))
563 FillTypeTable (fieldInfo.FieldType);
565 else if (propertyInfo != null) {
566 //If property is readonly or writeonly, do not serialize it.
567 //Exceptions are properties whose return type is array, ICollection or IEnumerable
568 //Indexers are not serialized unless the class Implements ICollection.
569 if (!(propertyInfo.PropertyType.IsArray || Implements (propertyInfo.PropertyType, typeof (ICollection)) ||
570 (propertyInfo.PropertyType != typeof (string) && Implements (propertyInfo.PropertyType, typeof (IEnumerable))))) {
571 if(!(propertyInfo.CanRead && propertyInfo.CanWrite) || propertyInfo.GetIndexParameters ().Length != 0)
575 XmlAttributes xmlAttributes = XmlAttributes.FromProperty (member, propertyInfo);
577 // If XmlAttributes have XmlIgnore, ignore this member
578 if (xmlAttributes.XmlIgnore)
581 // If this member is a XmlNs type, set the XmlNs object.
582 if (xmlAttributes.Xmlns) {
583 memberObj[1] = xmlAttributes;
586 // If the member is a attribute Type, Add to attribute list
587 if (xmlAttributes.isAttribute)
588 attributes.Add (xmlAttributes);
589 else //Add to elements
590 elements.Add (xmlAttributes);
592 // OtherWise add in the Hashtable.
593 memberTable.Add (member.Name, xmlAttributes);
595 if (xmlAttributes.XmlAnyAttribute != null || xmlAttributes.XmlText != null)
598 if (xmlAttributes.XmlElements.Count > 0) {
599 foreach (XmlElementAttribute elem in xmlAttributes.XmlElements) {
600 if (elem.Type != null)
601 FillTypeTable (elem.Type);
603 FillTypeTable (propertyInfo.PropertyType);
608 if (!IsInbuiltType (propertyInfo.PropertyType))
609 FillTypeTable (propertyInfo.PropertyType);
613 // Sort the attributes for the members according to their Order
614 // This is an extension to MS's Implementation and will be useful
615 // if our reflection does not return the same order of elements
618 BubbleSort (elements, XmlAttributes.attrComparer);
621 private void FillArrayType (Type type)
623 if (type.GetArrayRank () != 1)
624 throw new Exception ("MultiDimensional Arrays are not Supported");
626 Type arrayType = type.GetElementType ();
628 if (arrayType.IsArray)
629 FillArrayType (arrayType);
630 else if (!IsInbuiltType (arrayType))
631 FillTypeTable (arrayType);
634 private void FillICollectionType (Type type)
636 //Must have an public Indexer that takes an integer and
637 //a public Count Property which returns an int.
639 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
641 //Find a non indexer Count Property with return type of int
642 PropertyInfo countProp = type.GetProperty ("Count", flags, null, typeof (int), new Type[0], null);
643 if (countProp == null || !countProp.CanRead)
644 throw new Exception ("Cannot Serialize " + type + " because it implements ICollectoion, but does not implement public Count property");
645 //Find a indexer Item Property which takes an int
646 PropertyInfo itemProp = type.GetProperty ("Item", flags, null, null, new Type[1] {typeof (int)}, null);
647 if (itemProp == null || !itemProp.CanRead || !itemProp.CanWrite)
648 throw new Exception ("Cannot Serialize " + type + " because it does not have a read/write indexer property that takes an int as argument");
649 FillTypeTable (itemProp.PropertyType);
653 private void FillIEnumerableType (Type type)
655 //Must implement a public Add method that takes a single parameter.
656 //The Add method's parameter must be of the same type as is returned from
657 //the Current property on the value returned from GetEnumerator, or one of that type's bases.
659 // We currently ignore enumerable types anyway, so this method was junked.
660 // The code did not do what the documentation above says (if that is even possible!)
664 private void FillEnum (Type type)
666 Hashtable memberTable = new Hashtable ();
667 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
668 typeTable.Add (type, memberTable);
669 string[] names = Enum.GetNames (type);
671 foreach (string name in names) {
672 MemberInfo[] members = type.GetMember (name);
673 if (members.Length != 1)
674 throw new Exception("Should never happen. Enum member not present or more than one. " + name);
675 XmlAttributes xmlAttributes = new XmlAttributes (members[0]);
677 if (xmlAttributes.XmlIgnore)
680 if (xmlAttributes.XmlEnum != null)
681 memberTable.Add (members[0].Name, xmlAttributes.XmlEnum.Name);
683 memberTable.Add (members[0].Name, members[0].Name);
687 private bool HasDefaultConstructor (Type type)
689 ConstructorInfo defaultConstructor = type.GetConstructor (new Type[0]);
690 if (defaultConstructor == null || defaultConstructor.IsAbstract || defaultConstructor.IsStatic || !defaultConstructor.IsPublic)
696 private bool IsInbuiltType (Type type)
700 if (type.IsValueType || type == typeof (string) || type.IsPrimitive)
705 private static MemberInfo[] GetGraph(Type type)
707 ArrayList typeGraph = new ArrayList ();
708 GetGraph (type, typeGraph);
709 return (MemberInfo[]) typeGraph.ToArray (typeof (MemberInfo));
712 private static void GetGraph (Type type, ArrayList typeGraph)
714 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
715 if (type.BaseType == null)
717 GetGraph (type.BaseType, typeGraph);
719 typeGraph.AddRange (type.GetFields (flags));
720 typeGraph.AddRange (type.GetProperties (flags));
723 private string GetXmlValue (object value)
729 Type type = value.GetType ();
731 if (typeTable.ContainsKey (type)) {
732 Hashtable memberTable = (Hashtable) (typeTable[type]);
733 if (type.IsDefined (typeof (FlagsAttribute), false)) {
734 //If value is exactly a single enum member
735 if (memberTable.Contains (value.ToString ()))
736 return (string) memberTable[value.ToString ()];
739 int enumval = (int) value;
740 string[] names = Enum.GetNames (type);
742 foreach (string key in names) {
743 if (!memberTable.ContainsKey (key))
746 //Otherwise multiple values.
747 int val = (int) Enum.Parse (type, key);
748 if (val != 0 && (enumval & val) == val)
749 retval += " " + (string) memberTable[Enum.GetName (type, val)];
752 retval = retval.Trim ();
754 if (retval.Length == 0)
759 else if (memberTable.ContainsKey (value.ToString ()))
760 return (string) memberTable[value.ToString()];
765 throw new Exception ("Unknown Enumeration");
768 return (bool) value ? "true" : "false";
769 if (value is XmlQualifiedName) {
770 if (((XmlQualifiedName) value).IsEmpty)
773 return (value == null) ? null : value.ToString ();
776 [MonoTODO ("Remove FIXMEs")]
777 private static void ProcessAttributes (XmlAttributes attrs, Hashtable memberTable)
779 if (attrs.XmlAnyAttribute != null) {
782 foreach (XmlAnyElementAttribute anyelem in attrs.XmlAnyElements)
783 memberTable.Add (new XmlQualifiedName (anyelem.Name, anyelem.Namespace), attrs);
785 if (attrs.XmlArray != null) {
789 foreach (XmlArrayItemAttribute item in attrs.XmlArrayItems)
790 memberTable.Add (new XmlQualifiedName (item.ElementName, item.Namespace), attrs);
792 if (attrs.XmlAttribute != null)
793 memberTable.Add (new XmlQualifiedName (attrs.XmlAttribute.AttributeName,attrs.XmlAttribute.Namespace), attrs);
795 if (attrs.XmlChoiceIdentifier != null) {
799 foreach (XmlElementAttribute elem in attrs.XmlElements)
800 memberTable.Add (new XmlQualifiedName (elem.ElementName, elem.Namespace), attrs);
802 if (attrs.XmlEnum != null) {
806 if (attrs.XmlType != null)
807 memberTable.Add (new XmlQualifiedName (attrs.XmlType.TypeName, attrs.XmlType.Namespace), attrs);
810 private bool Implements (Type type, Type interfaceType)
812 return (type.GetInterface (interfaceType.Name) == interfaceType);
815 private static void BubbleSort (ArrayList array, IComparer comparer)
817 int len = array.Count;
819 for (int i=0; i < len; i++) {
820 for (int j=0; j < len -i -1; j++) {
823 if (comparer.Compare (obj2 , obj1 ) < 0) {
830 #endregion // Methods