Hi,

I sent this patch almost a week ago and have not seen it be merged into
CVS or rejected. Hence this keep-alive email 8-)

Best regards,

-elan

> I'm resending with tabs as requested.
> 
> -elan
> 
> > * XmlCustomFormatter.cs: Support for converting byte arrays to and
> from
> > Base64.
> >
> > * XmlSerialize.cs: Fix serialization of arrays to work better.
> > Implemented simple XML deserialization, works for nested objects,
> > arrays, etc. Most complex thing I tested was a structure containing
> two
> > arrays of structures. The code is fairly simple and easy to extend.
> >
> > My first C# and first Mono work, so please don't laugh.
> >
> > Best regards,
> >
> > -elan
Index: System.Xml/XmlTextReader.cs
===================================================================
RCS file: /mono/mcs/class/System.XML/System.Xml/XmlTextReader.cs,v
retrieving revision 1.49
diff -u -r1.49 XmlTextReader.cs
--- System.Xml/XmlTextReader.cs 16 Feb 2003 14:31:06 -0000      1.49
+++ System.Xml/XmlTextReader.cs 27 Feb 2003 20:10:52 -0000
@@ -1604,7 +1604,7 @@
                private string ReadName ()
                {
                        if (!XmlChar.IsFirstNameChar (PeekChar ()))
-                               throw new XmlException ("a name did not start with a 
legal character");
+                               throw new XmlException ("a name did not start with a 
legal character " + PeekChar());
 
                        nameLength = 0;
 
Index: System.Xml.Serialization/XmlCustomFormatter.cs
===================================================================
RCS file: /mono/mcs/class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs,v
retrieving revision 1.4
diff -u -r1.4 XmlCustomFormatter.cs
--- System.Xml.Serialization/XmlCustomFormatter.cs      19 Sep 2002 07:16:01 -0000     
 1.4
+++ System.Xml.Serialization/XmlCustomFormatter.cs      27 Feb 2003 20:10:53 -0000
@@ -16,10 +16,9 @@
 
                #region Methods
 
-               [MonoTODO]
-               internal static byte[] FromByteArrayBase64 (byte[] value)
+               internal static string FromByteArrayBase64 (byte[] value)
                {
-                       throw new NotImplementedException ();
+                       return Convert.ToBase64String(value);
                }
 
                internal static string FromByteArrayHex (byte[] value)
@@ -86,6 +85,11 @@
                        foreach (string token in tokens)
                                output.Append (FromXmlNmToken (token));
                        return output.ToString ();
+               }
+
+               internal static byte[] ToByteArrayBase64 (string value)
+               {
+                       return Convert.FromBase64String(value);
                }
 
                internal static char ToChar (string value)
Index: System.Xml.Serialization/XmlSerializationWriter.cs
===================================================================
RCS file: 
/mono/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriter.cs,v
retrieving revision 1.6
diff -u -r1.6 XmlSerializationWriter.cs
--- System.Xml.Serialization/XmlSerializationWriter.cs  13 Sep 2002 21:15:11 -0000     
 1.6
+++ System.Xml.Serialization/XmlSerializationWriter.cs  27 Feb 2003 20:10:53 -0000
@@ -84,7 +84,7 @@
                        return new InvalidOperationException (message);
                }
 
-               protected static byte[] FromByteArrayBase64 (byte[] value)
+               protected static string FromByteArrayBase64 (byte[] value)
                {
                        return XmlCustomFormatter.FromByteArrayBase64 (value);
                }
Index: System.Xml.Serialization/XmlSerializer.cs
===================================================================
RCS file: /mono/mcs/class/System.XML/System.Xml.Serialization/XmlSerializer.cs,v
retrieving revision 1.18
diff -u -r1.18 XmlSerializer.cs
--- System.Xml.Serialization/XmlSerializer.cs   16 Feb 2003 07:27:47 -0000      1.18
+++ System.Xml.Serialization/XmlSerializer.cs   27 Feb 2003 20:10:54 -0000
@@ -6,9 +6,11 @@
 //   John Donagher ([EMAIL PROTECTED])
 //   Ajay kumar Dwivedi ([EMAIL PROTECTED])
 //   Tim Coleman ([EMAIL PROTECTED])
+//   Elan Feingold ([EMAIL PROTECTED])
 //
 // (C) 2002 John Donagher, Ajay kumar Dwivedi
 // Copyright (C) Tim Coleman, 2002
+// (C) 2003 Elan Feingold
 // 
 
 using System;
@@ -17,6 +19,7 @@
 using System.Reflection;
 using System.Xml;
 using System.Xml.Schema;
+using System.Text;
 
 namespace System.Xml.Serialization {   
        /// <summary>
@@ -80,10 +83,10 @@
                }
 
                public XmlSerializer (Type type,
-                                     XmlAttributeOverrides overrides,
-                                     Type [] extraTypes,
-                                     XmlRootAttribute root,
-                                     string defaultNamespace)
+                                         XmlAttributeOverrides overrides,
+                                         Type [] extraTypes,
+                                         XmlRootAttribute root,
+                                         string defaultNamespace)
                {
                        if (type == null)
                                throw new ArgumentNullException ("type");
@@ -162,22 +165,208 @@
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public object Deserialize (Stream stream)
                {
-                       throw new NotImplementedException ();
+                       XmlTextReader xmlReader = new XmlTextReader(stream);
+                       return Deserialize(xmlReader);
                }
-               [MonoTODO]
+
                public object Deserialize (TextReader textReader)
                {
-                       throw new NotImplementedException ();
+                       XmlTextReader xmlReader = new XmlTextReader(textReader);
+                       return Deserialize(xmlReader);
                }
-               [MonoTODO]
-               public object Deserialize (XmlReader xmlReader)
+
+               public bool DeserializeComposite(XmlReader xmlReader, ref Object 
theObject)
                {
-                       throw new NotImplementedException ();
+                       Type objType = theObject.GetType();
+                       bool retVal      = true;
+
+                       //Console.WriteLine("DeserializeComposite({0})", objType);
+                       
+                       // Are we at an empty element?
+                       if (xmlReader.IsEmptyElement == true)
+                               return retVal;
+
+                       // Read each field, counting how many we find.
+                       for (int numFields=0; xmlReader.Read(); )
+                       {
+                               XmlNodeType xmlNodeType = xmlReader.NodeType;
+                               bool            isEmpty         = 
xmlReader.IsEmptyElement;
+                               
+                               if (xmlNodeType == XmlNodeType.Element)
+                               {
+                                       // Read the field.
+                                       DeserializeField(xmlReader, ref theObject, 
xmlReader.Name);
+                                       numFields++;
+                               }
+                               else if (xmlNodeType == XmlNodeType.EndElement)
+                               {
+                                       if (numFields == 0)
+                                       {
+                                               //Console.WriteLine("Empty object 
deserialized, ignoring.");
+                                               retVal = false;
+                                       }
+                                       
+                                       return retVal;
+                               }
+                       }
+
+                       return retVal;
                }
 
+               public void DeserializeField(XmlReader  xmlReader,
+                                                                        ref Object 
theObject,
+                                                                        String        
 fieldName)
+               {
+                       // Get the type
+                       FieldInfo fieldInfo        = 
theObject.GetType().GetField(fieldName);
+                       Type      fieldType        = fieldInfo.FieldType;
+                       Object    value            = null;
+                       bool      isEmptyField = xmlReader.IsEmptyElement;
+
+                       //Console.WriteLine("DeserializeField({0} of type {1}", 
fieldName, fieldType);
+
+                       if (fieldType.IsArray && fieldType != typeof(System.Byte[]))
+                       {
+                               // Create an empty array list.
+                               ArrayList list = new ArrayList();
+
+                               // Call out to deserialize it.
+                               DeserializeArray(xmlReader, list, 
fieldType.GetElementType());
+                               value = list.ToArray(fieldType.GetElementType());
+                       }
+                       else if (isEmptyField == true && fieldType.IsArray)
+                       {
+                               // Must be a byte array, just create an empty one.
+                               value = new byte[0];
+                       }
+                       else if (isEmptyField == false && 
+                                        (IsInbuiltType(fieldType) || fieldType.IsEnum 
|| fieldType.IsArray))
+                       {
+                               // Built in, set it.
+                               while (xmlReader.Read())
+                               {
+                                       if (xmlReader.NodeType == XmlNodeType.Text)
+                                       {
+                                               //Console.WriteLine(" -> value is 
'{0}'", xmlReader.Value);
+                                               
+                                               if (fieldType == typeof(Guid))
+                                                       value = 
XmlConvert.ToGuid(xmlReader.Value);
+                                               else if (fieldType == typeof(Boolean))
+                                                       value = 
XmlConvert.ToBoolean(xmlReader.Value);
+                                               else if (fieldType == typeof(String))
+                                                       value = xmlReader.Value;
+                                               else if (fieldType == typeof(Int64))
+                                                       value = 
XmlConvert.ToInt64(xmlReader.Value);
+                                               else if (fieldType == typeof(DateTime))
+                                                       value = 
XmlConvert.ToDateTime(xmlReader.Value);
+                                               else if (fieldType.IsEnum)
+                                                       value = Enum.Parse(fieldType, 
xmlReader.Value);
+                                               else if (fieldType == 
typeof(System.Byte[]))
+                                                       value = 
XmlCustomFormatter.ToByteArrayBase64(xmlReader.Value);
+                                               else
+                                                       Console.WriteLine("Error (type 
is '{0})'", fieldType);
+                                               
+                                               break;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               //Console.WriteLine("Creating new {0}", fieldType);
+
+                               // Create the new complex object.
+                               value = System.Activator.CreateInstance(fieldType);
+
+                               // Recurse, allowing the method to whack the object if 
it's empty.
+                               DeserializeComposite(xmlReader, ref value);
+                       }
+
+                       //Console.WriteLine(" Setting {0} to '{1}'", fieldName, value);
+
+                       // Set the field value.
+                       theObject.GetType().InvokeMember(fieldName,
+                                                                                      
  BindingFlags.SetField, 
+                                                                                      
  null,
+                                                                                      
  theObject, 
+                                                                                      
  new Object[] { value },
+                                                                                      
  null, null, null);
+
+                       // We need to munch the end.
+                       if (IsInbuiltType(fieldType) || 
+                               fieldType.IsEnum                 || 
+                               fieldType == typeof(System.Byte[]))
+                       {
+                               if (isEmptyField == false)
+                                       while (xmlReader.Read() && xmlReader.NodeType 
!= XmlNodeType.EndElement)
+                                               ;
+                       }
+                       
+               }
+
+               public void DeserializeArray(XmlReader xmlReader, ArrayList theList, 
Type theType)
+               {
+                       //Console.WriteLine(" DeserializeArray({0})", theType);
+
+                       if (xmlReader.IsEmptyElement)
+                       {
+                               //Console.WriteLine("  DeserializeArray -> empty, 
nothing to do here");
+                               return;
+                       }
+
+                       while (xmlReader.Read())
+                       {
+                               XmlNodeType xmlNodeType = xmlReader.NodeType;
+                               bool            isEmpty         = 
xmlReader.IsEmptyElement;
+
+                               if (xmlNodeType == XmlNodeType.Element)
+                               {
+                                       // Must be an element of the array, create it.
+                                       Object obj = 
System.Activator.CreateInstance(theType);
+
+                                       //Console.WriteLine("  created obj of type 
'{0}'", obj.GetType());
+
+                                       // Deserialize and add.
+                                       if (DeserializeComposite(xmlReader, ref obj))
+                                       {
+                                               theList.Add(obj);
+                                       }
+                               }
+                               
+                               if ((xmlNodeType == XmlNodeType.Element && isEmpty) ||
+                                       (xmlNodeType == XmlNodeType.EndElement))
+                               {
+                                       return;
+                               }
+                       }
+               }
+
+               public object Deserialize(XmlReader xmlReader)
+               {
+                       Object obj = null;
+
+                       // Read each node in the tree.
+                       while (xmlReader.Read())
+                       {
+                               if (xmlReader.NodeType == XmlNodeType.Element)
+                               {
+                                       // Create the top level object.
+                                       //Console.WriteLine("Creating '{0}'", 
xsertype.FullName);
+                                       obj = 
System.Activator.CreateInstance(xsertype);
+
+                                       // Deserialize it.
+                                       DeserializeComposite(xmlReader, ref obj);
+                               }
+                               else if (xmlReader.NodeType == XmlNodeType.EndElement)
+                               {
+                                       return obj;
+                               }
+                       }                                  
+
+                       return obj;
+               }  
+
                protected virtual object Deserialize (XmlSerializationReader reader)
                {
                        // This is what MS does!!!
@@ -266,7 +455,7 @@
                        object [] memberObj = (object []) typeTable [objType];
                        if (memberObj == null)
                                throw new Exception ("Unknown Type " + objType +
-                                                    " encountered during 
Serialization");
+                                                        " encountered during 
Serialization");
 
                        Hashtable memberTable = (Hashtable) memberObj [0];
                        XmlAttributes xmlAttributes = (XmlAttributes) memberTable [""];
@@ -369,7 +558,7 @@
 
                        Type objType = o.GetType ();
                        
-                       if (IsInbuiltType(objType)) 
+                       if (IsInbuiltType(objType))
                        {
                                SerializeBuiltIn (writer, o);
                                return;
@@ -420,7 +609,7 @@
 
                                attributeName = xmlAttributes.GetAttributeName 
(attributeType, member.Name);
                                attributeNs = xmlAttributes.GetAttributeNamespace 
(attributeType);
-                       
+
                                if (attributeValue is XmlQualifiedName) {
                                        XmlQualifiedName qname = (XmlQualifiedName) 
attributeValue;
 
@@ -474,12 +663,12 @@
                                        elementValue = fieldInfo.GetValue (o);
                                }
                                else {
-                                       elementType  = propertyInfo.PropertyType;
+                                       elementType      = propertyInfo.PropertyType;
                                        elementValue = propertyInfo.GetValue (o, null);
                                }
-
                                elementName = xmlElements.GetElementName (elementType, 
member.Name);
                                elementNs = xmlElements.GetElementNamespace 
(elementType);
+
                                WriteElement (writer, xmlElements, elementName, 
elementNs, elementType, elementValue);
                        }
                }
@@ -539,7 +728,7 @@
                                        for (int i = 0; i < count; i++) 
                                        {
                                                object itemValue = itemInfo.GetValue 
(value, new object[1] {i});
-                                               Type   itemType  = 
itemInfo.PropertyType;
+                                               Type   itemType  = 
itemInfo.PropertyType;
 
                                                if (itemValue != null) 
                                                {
@@ -558,7 +747,7 @@
                        }
                        else if (type.IsEnum) 
                        {
-                               // FIXME
+                               writer.WriteString(GetXmlValue(value));
                        }
                        else
                        { //Complex Type
@@ -581,9 +770,8 @@
                        string arrayTypeName = 
TypeTranslator.GetTypeData(arrayType).ElementName;
                        
                        TypeData td = TypeTranslator.GetTypeData (arrayType);
-                       writer.WriteStartElement (td.ElementName);
-                       Console.WriteLine(td.ElementName);
-                       //Special Treatment for Byte array
+
+                       // Special Treatment for Byte array
                        if(arrayType.Equals(typeof(byte)))
                        {
                                WriteBuiltinValue(writer,o);
@@ -592,8 +780,10 @@
                        {
                                for(int i=0; i< arr.Length; i++)
                                {
+                                       writer.WriteStartElement (td.ElementName);
+
                                        object value = arr.GetValue(i);
-                                       if (IsInbuiltType (arrayType)) 
+                                       if (IsInbuiltType (arrayType))
                                        {
                                                WriteBuiltinValue(writer, value);
                                        }
@@ -601,9 +791,10 @@
                                        {
                                                SerializeMembers(writer, value, false);
                                        }
+
+                                       writer.WriteEndElement();
                                }
                        }
-                       writer.WriteEndElement();
                }
 
                /// <summary>
@@ -615,6 +806,7 @@
                [MonoTODO ("Remove FIXMEs")]
                private void FillTypeTable (Type type)
                {
+                       // If it's already in the table, don't add it again.
                        if (typeTable.Contains (type))
                                return;
 
@@ -634,8 +826,8 @@
                        }
                        else {
                                //There must be a public constructor
-                               if (!HasDefaultConstructor (type))
-                                       throw new Exception ("Can't Serialize Type " + 
type.Name + " since it does not have default Constructor");
+                               //if (!HasDefaultConstructor (type))
+                               //throw new Exception ("Can't Serialize Type " + 
type.Name + " since it does not have default Constructor");
 
                                if (type.GetInterface ("ICollection") == typeof 
(System.Collections.ICollection)) {
                                        FillICollectionType (type);
@@ -681,6 +873,7 @@
                                        continue;
 
                                if (fieldInfo != null) {
+
                                        //If field is readOnly or const, do not 
serialize it.
                                        if (fieldInfo.IsLiteral || 
fieldInfo.IsInitOnly)
                                                continue;
@@ -724,11 +917,15 @@
                                                FillTypeTable (fieldInfo.FieldType);
                                } 
                                else if (propertyInfo != null) {
+
                                        //If property is readonly or writeonly, do not 
serialize it.
                                        //Exceptions are properties whose return type 
is array, ICollection or IEnumerable
                                        //Indexers are not serialized unless the class 
Implements ICollection.
-                                       if (!(propertyInfo.PropertyType.IsArray || 
Implements (propertyInfo.PropertyType, typeof (ICollection)) || 
-                                               (propertyInfo.PropertyType != typeof 
(string) && Implements (propertyInfo.PropertyType, typeof (IEnumerable))))) {
+                                       if (!(propertyInfo.PropertyType.IsArray || 
+                                                 Implements 
(propertyInfo.PropertyType, typeof (ICollection)) || 
+                                                 (propertyInfo.PropertyType != typeof 
(string) && 
+                                                  Implements 
(propertyInfo.PropertyType, typeof (IEnumerable)))))
+                                       {
                                                if(!(propertyInfo.CanRead && 
propertyInfo.CanWrite) || propertyInfo.GetIndexParameters ().Length != 0)
                                                        continue;
                                        }
@@ -858,9 +1055,12 @@
                {
                        if (type.IsEnum)
                                return false;
-                       if (type.IsValueType || type == typeof (string) || 
type.IsPrimitive)
+                       if (/* type.IsValueType || */type == typeof (string) || 
type.IsPrimitive)
                                return true;
-                       if (type == typeof (DateTime) || type == typeof (XmlNode) || 
type.IsSubclassOf (typeof (XmlNode)))
+                       if (type == typeof (DateTime) || 
+                               type == typeof (Guid)     ||
+                               type == typeof (XmlNode)  || 
+                               type.IsSubclassOf (typeof (XmlNode)))
                                return true;
                                
                        return false;
@@ -931,7 +1131,7 @@
                        }
                        #endregion
                        if (value is byte[])
-                               return 
XmlCustomFormatter.FromByteArrayHex((byte[])value);
+                               return 
XmlCustomFormatter.FromByteArrayBase64((byte[])value);
                        if (value is Guid)
                                return XmlConvert.ToString((Guid)value);
                        if(value is DateTime)

Reply via email to