+2003-06-05 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * SoapReflectionImporter.cs: implemented.
+ * TypeTranslator.cs: added IsPrimitive() method
+ * TypeMapping.cs: Added RelatedMaps property that returns all maps directly or indirectly
+ used by that one. Also added Format property, that can be literal or encoded.
+ * XmlReflectionImporter.cs: little fixes. Moved some methods to ReflectionHelper.
+ * XmlReflectionMember.cs: added constructor that accepts SoapAttributes
+ * XmlSerializationReader.cs: implemented many methods needed to support encoded format.
+ * XmlSerializationReaderInterpreter.cs: added support for encoded format.
+ * XmlSerializationWriter.cs: added support for encoded format.
+ * XmlSerializationWriterInterpreter.cs: added support for encoded format.
+ * XmlTypeMapElementInfo.cs: added some properties needed to support encoded format
+ * XmlTypeMapMemberAttribute.cs: added MappedType property (enum values can be attributes,
+ and a map is needed for them).
+ * XmlTypeMapMemberElement.cs: small fixes.
+ * XmlTypeMapping.cs: added some properties and methods needed to support encoded format
+ * ReflectionHelper.cs: added. Has some methods shared by the reflection importers.
+
2003-06-01 Miguel de Icaza <miguel@ximian.com>
* XmlSerializationReader.cs (UnknownAttribute, UnknownNode,
--- /dev/null
+//
+// System.Xml.Serialization.ReflectionHelper
+//
+// Author:
+// Lluis Sanchez Gual (lluis@ximian.com)
+//
+// Copyright (C) 2003 Ximian, Inc.\r
+//
+
+using System.Reflection;
+using System.Collections;
+\r
+namespace System.Xml.Serialization\r
+{\r
+ internal class ReflectionHelper\r
+ {\r
+ Hashtable _clrTypes = new Hashtable ();
+ Hashtable _schemaTypes = new Hashtable ();
+\r
+ public void RegisterSchemaType (XmlTypeMapping map, string xmlType, string ns)
+ {
+ string mapKey = xmlType + "/" + ns;
+ if (!_schemaTypes.ContainsKey (xmlType))
+ _schemaTypes.Add (mapKey, map);
+ }
+
+ public XmlTypeMapping GetRegisteredSchemaType (string xmlType, string ns)
+ {
+ string mapKey = xmlType + "/" + ns;
+ return _schemaTypes[mapKey] as XmlTypeMapping;
+ }
+
+ public void RegisterClrType (XmlTypeMapping map, Type type, string ns)
+ {
+ if (type == typeof(object)) ns = "";
+ string mapKey = type.FullName + "/" + ns;
+ if (!_clrTypes.ContainsKey (mapKey))
+ _clrTypes.Add (mapKey, map);
+ }
+
+ public XmlTypeMapping GetRegisteredClrType (Type type, string ns)
+ {
+ if (type == typeof(object)) ns = "";
+ string mapKey = type.FullName + "/" + ns;
+ return _clrTypes[mapKey] as XmlTypeMapping;
+ } \r
+\r
+ public Exception CreateError (XmlTypeMapping map, string message)
+ {
+ return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
+ }
+ }\r
+}\r
\r
using System.Reflection;\r
using System.Xml;\r
+using System.Xml.Schema;\r
+using System.Collections;
\r
namespace System.Xml.Serialization {\r
public class SoapReflectionImporter {\r
\r
+ SoapAttributeOverrides attributeOverrides;\r
+ string initialDefaultNamespace;\r
+ ArrayList includedTypes;
+ ArrayList relatedMaps = new ArrayList ();
+ ReflectionHelper helper = new ReflectionHelper();
+ internal const string EncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
+\r
#region Constructors\r
\r
- [MonoTODO]\r
- public SoapReflectionImporter ()\r
+ public SoapReflectionImporter (): this (null, null)\r
{ \r
- throw new NotImplementedException ();\r
}\r
\r
- [MonoTODO]\r
- public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides)\r
+ public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides): this (attributeOverrides, null)\r
{ \r
- throw new NotImplementedException ();\r
}\r
\r
- [MonoTODO]\r
- public SoapReflectionImporter (string defaultNamespace)\r
- { \r
- throw new NotImplementedException ();\r
+ public SoapReflectionImporter (string defaultNamespace): this (null, defaultNamespace)\r
+ {\r
}\r
\r
- [MonoTODO]\r
public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides, string defaultNamespace)\r
{ \r
- throw new NotImplementedException ();\r
+ if (defaultNamespace == null) initialDefaultNamespace = String.Empty;
+ else initialDefaultNamespace = defaultNamespace;
+
+ if (attributeOverrides == null) this.attributeOverrides = new SoapAttributeOverrides();
+ else this.attributeOverrides = attributeOverrides;\r
}\r
\r
#endregion // Constructors\r
\r
#region Methods\r
\r
- [MonoTODO]\r
public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members)\r
- { \r
- throw new NotImplementedException ();\r
+ {\r
+ return ImportMembersMapping (elementName, ns, members, true, true, false);\r
}\r
\r
- [MonoTODO]\r
public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors)\r
{ \r
- throw new NotImplementedException ();\r
+ return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, false);\r
}\r
\r
- [MonoTODO]\r
public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate)\r
{ \r
- throw new NotImplementedException ();\r
+ XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
+ for (int n=0; n<members.Length; n++)
+ {
+ XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
+ mapping[n] = new XmlMemberMapping (members[n], mapMem);
+ }
+ XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+ mps.RelatedMaps = relatedMaps;\r
+ mps.Format = SerializationFormat.Encoded;\r
+ return mps;\r
}\r
\r
- [MonoTODO]\r
public XmlTypeMapping ImportTypeMapping (Type type)\r
{ \r
- throw new NotImplementedException ();\r
+ return ImportTypeMapping (type, null);\r
}\r
\r
- [MonoTODO]\r
public XmlTypeMapping ImportTypeMapping (Type type, string defaultNamespace)\r
{ \r
- throw new NotImplementedException ();\r
+ if (type == null)
+ throw new ArgumentNullException ("type");
+
+ if (type == typeof (void))
+ throw new InvalidOperationException ("Type " + type.Name + " may not be serialized.");
+
+ if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
+ if (defaultNamespace == null) defaultNamespace = string.Empty;
+
+ XmlTypeMapping map;
+ switch (TypeTranslator.GetTypeData(type).SchemaType)
+ {
+ case SchemaTypes.Class: map = ImportClassMapping (type, defaultNamespace); break;
+ case SchemaTypes.Array: map = ImportListMapping (type, defaultNamespace); break;
+ case SchemaTypes.XmlNode: throw CreateTypeException (type);
+ case SchemaTypes.Primitive: map = ImportPrimitiveMapping (type, defaultNamespace); break;
+ case SchemaTypes.Enum: map = ImportEnumMapping (type, defaultNamespace); break;
+ case SchemaTypes.DataSet:
+ default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
+ }\r
+ map.RelatedMaps = relatedMaps;\r
+ map.Format = SerializationFormat.Encoded;\r
+ return map;\r
}\r
\r
- [MonoTODO]\r
- public void IncludeType (Type type)\r
- { \r
- throw new NotImplementedException ();\r
+ XmlTypeMapping CreateTypeMapping (TypeData typeData, string defaultXmlType, string defaultNamespace)
+ {
+ string membersNamespace = defaultNamespace;
+ string elementName;
+ SoapAttributes atts = null;
+ if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
+
+ if (!typeData.IsListType)
+ {
+ if (attributeOverrides != null)
+ atts = attributeOverrides[typeData.Type];
+ }
+
+ if (atts == null)
+ atts = new SoapAttributes (typeData.Type);
+
+ if (atts.SoapType != null)
+ {
+ if (atts.SoapType.Namespace != null && atts.SoapType.Namespace != string.Empty)
+ membersNamespace = atts.SoapType.Namespace;
+
+ if (atts.SoapType.TypeName != null && atts.SoapType.TypeName != string.Empty)
+ defaultXmlType = atts.SoapType.TypeName;
+ }
+
+ elementName = defaultXmlType;
+
+ if (membersNamespace == null) membersNamespace = "";
+ XmlTypeMapping map = new XmlTypeMapping (elementName, membersNamespace, typeData, defaultXmlType);
+
+ relatedMaps.Add (map);
+ return map;
+ }
+\r
+ XmlTypeMapping ImportClassMapping (Type type, string defaultNamespace)
+ {
+ if (type.IsValueType) throw CreateStructException (type);
+ if (type == typeof (object)) defaultNamespace = XmlSchema.Namespace;
+
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ if (map != null) return map;
+
+ map = CreateTypeMapping (typeData, null, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
+ map.MultiReferenceType = true;
+
+ ClassMap classMap = new ClassMap ();
+ map.ObjectMap = classMap;
+
+ // Import members
+
+ try
+ {
+ ICollection members = GetReflectionMembers (type);
+ foreach (XmlReflectionMember rmember in members)
+ {
+ if (rmember.SoapAttributes.SoapIgnore) continue;
+ classMap.AddMember (CreateMapMember (rmember, map.Namespace));
+ }
+ }
+ catch (Exception ex) \r
+ {
+ throw helper.CreateError (map, ex.Message);
+ }
+
+ // Import derived classes
+
+ SoapIncludeAttribute[] includes = (SoapIncludeAttribute[])type.GetCustomAttributes (typeof (SoapIncludeAttribute), false);
+ for (int n=0; n<includes.Length; n++)
+ {
+ Type includedType = includes[n].Type;
+ if (!includedType.IsSubclassOf(type)) throw helper.CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
+ map.DerivedTypes.Add (ImportTypeMapping (includedType, defaultNamespace));
+ }
+
+ if (type == typeof (object) && includedTypes != null)
+ {
+ foreach (Type intype in includedTypes)
+ map.DerivedTypes.Add (ImportTypeMapping (intype));
+ }
+
+ // Register this map as a derived class of object
+
+ if (typeData.Type != typeof(object))
+ ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+
+ return map;
+ }
+\r
+ XmlTypeMapping ImportListMapping (Type type, string defaultNamespace)
+ {
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, EncodingNamespace);
+ if (map != null) return map;
+
+ ListMap obmap = new ListMap ();
+
+ map = CreateTypeMapping (typeData, "Array", EncodingNamespace);
+ helper.RegisterClrType (map, type, EncodingNamespace);
+ map.MultiReferenceType = true;
+ map.ObjectMap = obmap;
+
+ Type itemType = typeData.ListItemType;
+ TypeData itemTypeData = TypeTranslator.GetTypeData (itemType);
+ XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, itemTypeData);
+
+ if (elem.TypeData.IsComplexType) {
+ elem.MappedType = ImportTypeMapping (itemType);
+ elem.DataType = elem.MappedType.XmlType;
+ }
+ else
+ elem.DataType = itemTypeData.XmlType;
+
+ elem.ElementName = "Item";
+ elem.Namespace = string.Empty;
+ elem.IsNullable = true; // By default, items are nullable
+
+ XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
+ list.Add (elem);
+
+ obmap.ItemInfo = list;
+ ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+
+ return map;
}\r
+ \r
+ XmlTypeMapping ImportPrimitiveMapping (Type type, string defaultNamespace)
+ {
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ if (map != null) return map;
+ map = CreateTypeMapping (TypeTranslator.GetTypeData (type), null, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
+ return map;
+ }
+\r
+
+ XmlTypeMapping ImportEnumMapping (Type type, string defaultNamespace)
+ {
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ if (map != null) return map;
+ map = CreateTypeMapping (TypeTranslator.GetTypeData (type), null, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
+
+ string [] names = Enum.GetNames (type);
+ EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember[names.Length];
+ for (int n=0; n<names.Length; n++)
+ {
+ MemberInfo[] mem = type.GetMember (names[n]);
+ string xmlName = names[n];
+ object[] atts = mem[0].GetCustomAttributes (typeof(SoapEnumAttribute), false);
+ if (atts.Length > 0) xmlName = ((SoapEnumAttribute)atts[0]).Name;
+ members[n] = new EnumMap.EnumMapMember (xmlName, names[n]);
+ }
+
+ map.ObjectMap = new EnumMap (members);
+ ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+ return map;
+ }
+
+ public ICollection GetReflectionMembers (Type type)
+ {
+ ArrayList members = new ArrayList();
+ PropertyInfo[] properties = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
+ foreach (PropertyInfo prop in properties)
+ {
+ if (!prop.CanRead) continue;
+ SoapAttributes atts = attributeOverrides[type, prop.Name];
+ if (atts == null) atts = new SoapAttributes (prop);
+ if (atts.SoapIgnore) continue;
+ XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
+ members.Add (member);
+ }
+
+ FieldInfo[] fields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
+ foreach (FieldInfo field in fields)
+ {
+ SoapAttributes atts = attributeOverrides[type, field.Name];
+ if (atts == null) atts = new SoapAttributes (field);
+ if (atts.SoapIgnore) continue;
+ XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
+ members.Add (member);
+ }
+ return members;
+ }
+
+ private XmlTypeMapMember CreateMapMember (XmlReflectionMember rmember, string defaultNamespace)
+ {
+ XmlTypeMapMember mapMember;
+ SoapAttributes atts = rmember.SoapAttributes;
+ TypeData typeData = TypeTranslator.GetTypeData (rmember.MemberType);
+
+ if (atts.SoapAttribute != null)
+ {
+ // An attribute
+
+ if (atts.SoapElement != null)
+ throw new Exception ("SoapAttributeAttribute and SoapElementAttribute cannot be applied to the same member");
+
+ XmlTypeMapMemberAttribute mapAttribute = new XmlTypeMapMemberAttribute ();
+ if (atts.SoapAttribute.AttributeName == null)
+ mapAttribute.AttributeName = rmember.MemberName;
+ else
+ mapAttribute.AttributeName = atts.SoapAttribute.AttributeName;
+
+ mapAttribute.DataType = atts.SoapAttribute.DataType;
+ mapAttribute.Namespace = (atts.SoapAttribute.Namespace != null) ? atts.SoapAttribute.Namespace : "";
+ if (typeData.IsComplexType)
+ mapAttribute.MappedType = ImportTypeMapping (typeData.Type);
+
+ mapMember = mapAttribute;
+ }
+ else
+ {
+ if (typeData.SchemaType == SchemaTypes.Array) mapMember = new XmlTypeMapMemberList ();
+ else mapMember = new XmlTypeMapMemberElement ();
+
+ // Creates an ElementInfo that identifies the element
+ XmlTypeMapElementInfoList infoList = new XmlTypeMapElementInfoList();
+ XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (mapMember, typeData);
+
+ elem.ElementName = (atts.SoapElement != null && atts.SoapElement.ElementName != null) ? atts.SoapElement.ElementName : rmember.MemberName;
+ elem.Namespace = string.Empty;
+ elem.IsNullable = (atts.SoapElement != null) ? atts.SoapElement.IsNullable : false;
+ elem.DataType = (atts.SoapElement != null && atts.SoapElement.DataType != null) ? atts.SoapElement.DataType : typeData.XmlType;
+ if (typeData.IsComplexType)
+ elem.MappedType = ImportTypeMapping (typeData.Type);
+
+ infoList.Add (elem);
+ ((XmlTypeMapMemberElement)mapMember).ElementInfo = infoList;
+ }
+
+ mapMember.TypeData = typeData;
+ mapMember.Name = rmember.MemberName;
+ return mapMember;
+ }\r
+ \r
+ public void IncludeType (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException ("type");
+
+ if (includedTypes == null) includedTypes = new ArrayList ();
+ includedTypes.Add (type);
+ }
\r
[MonoTODO]\r
public void IncludeTypes (ICustomAttributeProvider provider)\r
throw new NotImplementedException ();\r
}\r
\r
+ Exception CreateTypeException (Type type)\r
+ {\r
+ return new NotSupportedException ("The type " + type.FullName + " may not be serialized with SOAP-encoded messages. Set the Use for your message to Literal");\r
+ }\r
+\r
+ Exception CreateStructException (Type type)\r
+ {\r
+ return new NotSupportedException ("Cannot serialize " + type.FullName + ". Nested structs are not supported with encoded SOAP");\r
+ }\r
+\r
+\r
+ \r
+\r
#endregion // Methods\r
}\r
}\r
return typeData;
}
+ public static bool IsPrimitive (Type type)
+ {
+ return GetTypeData (type).SchemaType == SchemaTypes.Primitive;
+ }
+
public static TypeData GetPrimitiveTypeData (string typeName)
{
return (TypeData) primitiveTypes[typeName];
//
using System;
+using System.Collections;
namespace System.Xml.Serialization
{
public abstract class XmlMapping
{
ObjectMap map;
+ ArrayList relatedMaps;
+ SerializationFormat format;
internal XmlMapping ()
{
get { return map; }
set { map = value; }
}
+
+ internal ArrayList RelatedMaps
+ {
+ get { return relatedMaps; }
+ set { relatedMaps = value; }
+ }
+
+ internal SerializationFormat Format
+ {
+ get { return format; }
+ set { format = value; }
+ }
}
internal class ObjectMap
{
}
+
+ internal enum SerializationFormat { Encoded, Literal }
}
ArrayList includedTypes;
Hashtable clrTypes = new Hashtable ();
Hashtable schemaTypes = new Hashtable ();
+ ReflectionHelper helper = new ReflectionHelper();
int arrayChoiceCount = 1;
#region Constructors
XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
mapping[n] = new XmlMemberMapping (members[n], mapMem);
}
- return new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+ XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+ mps.Format = SerializationFormat.Literal;\r
+ return mps;\r
}
public XmlTypeMapping ImportTypeMapping (Type type)
if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
if (defaultNamespace == null) defaultNamespace = string.Empty;
+ XmlTypeMapping map;
+
switch (TypeTranslator.GetTypeData(type).SchemaType)
{
- case SchemaTypes.Class: return ImportClassMapping (type, root, defaultNamespace);
- case SchemaTypes.Array: return ImportListMapping (type, root, defaultNamespace, null, 0);
- case SchemaTypes.XmlNode: return ImportXmlNodeMapping (type, root, defaultNamespace);
- case SchemaTypes.Primitive: return ImportPrimitiveMapping (type, root, defaultNamespace);
- case SchemaTypes.Enum: return ImportEnumMapping (type, root, defaultNamespace);
+ case SchemaTypes.Class: map = ImportClassMapping (type, root, defaultNamespace); break;
+ case SchemaTypes.Array: map = ImportListMapping (type, root, defaultNamespace, null, 0); break;
+ case SchemaTypes.XmlNode: map = ImportXmlNodeMapping (type, root, defaultNamespace); break;
+ case SchemaTypes.Primitive: map = ImportPrimitiveMapping (type, root, defaultNamespace); break;
+ case SchemaTypes.Enum: map = ImportEnumMapping (type, root, defaultNamespace); break;
case SchemaTypes.DataSet:
default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
}
+
+ map.Format = SerializationFormat.Literal;\r
+ return map;\r
}
XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
TypeData typeData = TypeTranslator.GetTypeData (type);
- XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
if (map != null) return map;
map = CreateTypeMapping (typeData, root, null, defaultNamespace);
- RegisterClrType (map, type, defaultNamespace);
- RegisterSchemaType (map, map.XmlType, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
+ helper.RegisterSchemaType (map, map.XmlType, defaultNamespace);
ClassMap classMap = new ClassMap ();
map.ObjectMap = classMap;
}
}
catch (Exception ex) {
- throw CreateError (map, ex.Message);
+ throw helper.CreateError (map, ex.Message);
}
// Import derived classes
for (int n=0; n<includes.Length; n++)
{
Type includedType = includes[n].Type;
- if (!includedType.IsSubclassOf(type)) throw CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
+ if (!includedType.IsSubclassOf(type)) throw helper.CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
map.DerivedTypes.Add (ImportTypeMapping (includedType, root, defaultNamespace));
}
string name = baseName;
do {
- XmlTypeMapping foundMap = GetRegisteredSchemaType (name, defaultNamespace);
+ XmlTypeMapping foundMap = helper.GetRegisteredSchemaType (name, defaultNamespace);
if (foundMap == null) nameCount = -1;
else if (obmap.Equals (foundMap.ObjectMap)) return foundMap;
else name = baseName + (nameCount++);
// Register this map as a derived class of object
- RegisterSchemaType (map, name, defaultNamespace);
+ helper.RegisterSchemaType (map, name, defaultNamespace);
ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
return map;
XmlTypeMapping ImportXmlNodeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
if (map != null) return map;
// Registers the maps for XmlNode and XmlElement
XmlTypeMapping nodeMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlNode)), root, null, defaultNamespace);
- RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
+ helper.RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
XmlTypeMapping elemMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlElement)), root, null, defaultNamespace);
- RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
+ helper.RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
ImportTypeMapping (typeof(object)).DerivedTypes.Add (nodeMap);
ImportTypeMapping (typeof(object)).DerivedTypes.Add (elemMap);
nodeMap.DerivedTypes.Add (elemMap);
- return GetRegisteredClrType (type, defaultNamespace);
+ return helper.GetRegisteredClrType (type, defaultNamespace);
}
XmlTypeMapping ImportPrimitiveMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
if (map != null) return map;
map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
- RegisterClrType (map, type, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
return map;
}
XmlTypeMapping ImportEnumMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
if (map != null) return map;
map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
- RegisterClrType (map, type, defaultNamespace);
+ helper.RegisterClrType (map, type, defaultNamespace);
string [] names = Enum.GetNames (type);
EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember[names.Length];
mapAttribute.DataType = atts.XmlAttribute.DataType;
mapAttribute.Form = atts.XmlAttribute.Form;
- mapAttribute.Namespace = (atts.XmlAttribute != null) ? atts.XmlAttribute.Namespace : "";
+ mapAttribute.Namespace = (atts.XmlAttribute.Namespace != null) ? atts.XmlAttribute.Namespace : "";
+ if (typeData.IsComplexType)
+ mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
+
mapMember = mapAttribute;
}
else if (typeData.SchemaType == SchemaTypes.Array)
// A list
XmlTypeMapMemberList member = new XmlTypeMapMemberList ();
- member.ElementName = (atts.XmlArray != null && atts.XmlArray.ElementName != null) ? atts.XmlArray.ElementName : rmember.MemberName;
- member.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
- member.ListTypeMapping = ImportListMapping (rmember.MemberType, null, member.Namespace, atts, 0);
// Creates an ElementInfo that identifies the array instance.
member.ElementInfo = new XmlTypeMapElementInfoList();
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, typeData);
- elem.ElementName = member.ElementName;
- elem.Namespace = member.Namespace;
- elem.MappedType = member.ListTypeMapping;
+ elem.ElementName = (atts.XmlArray != null && atts.XmlArray.ElementName != null) ? atts.XmlArray.ElementName : rmember.MemberName;
+ elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
+ elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
member.ElementInfo.Add (elem);
mapMember = member;
}
includedTypes.Add (type);
}
- void RegisterSchemaType (XmlTypeMapping map, string xmlType, string ns)
- {
- string mapKey = xmlType + "/" + ns;
- if (!schemaTypes.ContainsKey (xmlType))
- schemaTypes.Add (mapKey, map);
- }
-
- XmlTypeMapping GetRegisteredSchemaType (string xmlType, string ns)
- {
- string mapKey = xmlType + "/" + ns;
- return schemaTypes[mapKey] as XmlTypeMapping;
- }
-
- void RegisterClrType (XmlTypeMapping map, Type type, string ns)
- {
- if (type == typeof(object)) ns = "";
- string mapKey = type.FullName + "/" + ns;
- if (!clrTypes.ContainsKey (mapKey))
- clrTypes.Add (mapKey, map);
- }
-
- XmlTypeMapping GetRegisteredClrType (Type type, string ns)
- {
- if (type == typeof(object)) ns = "";
- string mapKey = type.FullName + "/" + ns;
- return clrTypes[mapKey] as XmlTypeMapping;
- }
-
- Exception CreateError (XmlTypeMapping map, string message)
- {
- return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
- }
-
#endregion // Methods
}
}
{\r
}\r
\r
- public XmlReflectionMember (string name, Type type, XmlAttributes attributes)\r
+ internal XmlReflectionMember (string name, Type type, XmlAttributes attributes)\r
{\r
memberName = name;\r
memberType = type;\r
xmlAttributes = attributes;\r
}\r
\r
+ internal XmlReflectionMember (string name, Type type, SoapAttributes attributes)\r
+ {\r
+ memberName = name;\r
+ memberType = type;\r
+ soapAttributes = attributes;\r
+ }\r
+\r
#endregion // Constructors\r
\r
#region Properties\r
using System;
using System.Collections;
using System.Xml;
+using System.Xml.Schema;
namespace System.Xml.Serialization {
public abstract class XmlSerializationReader {
XmlDocument document;
XmlReader reader;
ArrayList fixups;
- ArrayList collFixups;
- Hashtable readCallbacks;
+ Hashtable collFixups;
+ ArrayList collItemFixups;
Hashtable typesCallbacks;
ArrayList noIDTargets;
Hashtable targets;
+ Hashtable delayedListFixups;
XmlSerializer eventSource;
string w3SchemaNS;
string typeX;
string arrayType;
string anyType;
+ XmlQualifiedName arrayQName;
#endregion
internal void Initialize (XmlReader reader, XmlSerializer eventSource)
anyType = reader.NameTable.Add ("anyType");
this.reader = reader;
this.eventSource = eventSource;
+ arrayQName = new XmlQualifiedName ("Array", soapNS);
InitIDs ();
}
protected void AddFixup (CollectionFixup fixup)
{
- collFixups = EnsureArrayList (collFixups);
- collFixups.Add(fixup);
+ collFixups = EnsureHashtable (collFixups);
+ collFixups [fixup.Id] = fixup;
+
+ if (delayedListFixups != null && delayedListFixups.ContainsKey (fixup.Id))
+ fixup.CollectionItems = delayedListFixups [fixup.Id];
}
protected void AddFixup (Fixup fixup)
{
fixups = EnsureArrayList (fixups);
- fixups.Add(fixup);
+ fixups.Add (fixup);
+ }
+
+ void AddFixup (CollectionItemFixup fixup)
+ {
+ collItemFixups = EnsureArrayList (collItemFixups);
+ collItemFixups.Add(fixup);
}
protected void AddReadCallback (string name, string ns, Type type, XmlSerializationReadCallback read)
{
- XmlNameTable nt = reader.NameTable;
- XmlQualifiedName xqn = new XmlQualifiedName (nt.Add (name), nt.Add (ns));
- readCallbacks = EnsureHashtable (readCallbacks);
- readCallbacks.Add (xqn, read);
+ WriteCallbackInfo info = new WriteCallbackInfo ();
+ info.Type = type;
+ info.TypeName = name;
+ info.TypeNs = ns;
+ info.Callback = read;
typesCallbacks = EnsureHashtable (typesCallbacks);
- typesCallbacks.Add (xqn, type);
+ typesCallbacks.Add (new XmlQualifiedName (name, ns), info);
}
protected void AddTarget (string id, object o)
return (na != string.Empty);
}
- [MonoTODO ("Implement")]
protected object GetTarget (string id)
{
- throw new NotImplementedException ();
+ if (targets == null) return null;
+ return targets [id];
+ }
+
+ bool TargetReady (string id)
+ {
+ if (targets == null) return false;
+ return targets.ContainsKey (id);
}
[MonoTODO ("Implement")]
protected object ReadReferencedElement ()
{
- return ReadReferencedElement (null, null);
+ return ReadReferencedElement (Reader.LocalName, Reader.NamespaceURI);
+ }
+
+ WriteCallbackInfo GetCallbackInfo (XmlQualifiedName qname)
+ {
+ if (typesCallbacks == null)
+ {
+ typesCallbacks = new Hashtable ();
+ InitCallbacks ();
+ }
+ return (WriteCallbackInfo) typesCallbacks[qname];
}
protected object ReadReferencedElement (string name, string ns)
{
- string unused;
- return ReadReferencingElement (name, ns, false, out unused);
+ XmlQualifiedName qname = GetXsiType ();
+ if (qname == null) qname = new XmlQualifiedName (name, ns);
+
+ string id = Reader.GetAttribute ("id");
+ object ob;
+
+ if (qname == arrayQName)
+ {
+ CollectionFixup fixup = (collFixups != null) ? (CollectionFixup) collFixups[id] : null;
+ if (ReadList (out ob))
+ {
+ // List complete (does not contain references)
+ if (fixup != null)
+ {
+ fixup.Callback (fixup.Collection, ob);
+ collFixups.Remove (id);
+ ob = fixup.Collection;
+ }
+ }
+ else if (fixup != null)
+ {
+ fixup.CollectionItems = (object[])ob;
+ ob = fixup.Collection;
+ }
+ }
+ else
+ {
+ WriteCallbackInfo info = GetCallbackInfo (qname);
+ if (info == null) throw CreateUnknownTypeException (qname);
+ ob = info.Callback ();
+ }
+ AddTarget (id, ob);
+ return ob;
}
- protected void ReadReferencedElements ()
+ bool ReadList (out object resultList)
{
- string unused;
+ string arrayType = Reader.GetAttribute ("arrayType", soapNS);
+ XmlQualifiedName qn = ToXmlQualifiedName (arrayType);
+ int i = qn.Name.LastIndexOf ('[');
+ string dim = qn.Name.Substring (i);
+ string itemType = qn.Name.Substring (0,i);
+ int count = Int32.Parse (dim.Substring (1, dim.Length - 2));
+
+ Array list;
+ i = itemType.IndexOf ('['); if (i == -1) i = itemType.Length;
+ string baseType = itemType.Substring (0,i);
+ string arrayTypeName;
+
+ if (qn.Namespace == XmlSchema.Namespace)
+ arrayTypeName = TypeTranslator.GetPrimitiveTypeData (baseType).Type.FullName + itemType.Substring (i);
+ else
+ {
+ WriteCallbackInfo info = GetCallbackInfo (new XmlQualifiedName (baseType,qn.Namespace));
+ arrayTypeName = info.Type.FullName + itemType.Substring (i) + ", " + info.Type.Assembly.FullName;
+ }
+
+ list = Array.CreateInstance (Type.GetType (arrayTypeName), count);
+
+ bool listComplete = true;
+
+ Reader.ReadStartElement ();
+ for (int n=0; n<count; n++)
+ {
+ Reader.MoveToContent ();
+ string refid = Reader.GetAttribute ("href");
+ string id;
+ object item = ReadReferencingElement (itemType, qn.Namespace, out id);
+ if (id == null)
+ list.SetValue (item,n);
+ else
+ {
+ AddFixup (new CollectionItemFixup (list, n, id));
+ listComplete = false;
+ }
+ }
+ Reader.ReadEndElement ();
+
+ resultList = list;
+ return listComplete;
+ }
+
+ protected void ReadReferencedElements ()
+ {
reader.MoveToContent();
XmlNodeType nt = reader.NodeType;
while (nt != XmlNodeType.EndElement && nt != XmlNodeType.None) {
- ReadReferencingElement (null, null, true, out unused);
+ ReadReferencedElement ();
reader.MoveToContent ();
nt = reader.NodeType;
}
+
+ // Fix arrays
+
+ if (collItemFixups != null)
+ {
+ foreach (CollectionItemFixup itemFixup in collItemFixups)
+ itemFixup.Collection.SetValue (GetTarget (itemFixup.Id), itemFixup.Index);
+ }
+
+ // Fills collections
+
+ if (collFixups != null)
+ {
+ ICollection cfixups = collFixups.Values;
+ foreach (CollectionFixup fixup in cfixups)
+ fixup.Callback (fixup.Collection, fixup.CollectionItems);
+ }
+
+ // Fills class instances
+
+ if (fixups != null)
+ {
+ foreach (Fixup fixup in fixups)
+ fixup.Callback (fixup);
+ }
}
- [MonoTODO ("Implement")]
protected object ReadReferencingElement (out string fixupReference)
{
- return ReadReferencingElement (null, null, false, out fixupReference);
+ return ReadReferencingElement (Reader.LocalName, Reader.NamespaceURI, false, out fixupReference);
}
protected object ReadReferencingElement (string name, string ns, out string fixupReference)
return ReadReferencingElement (name, ns, false, out fixupReference);
}
- [MonoTODO]
protected object ReadReferencingElement (string name,
string ns,
bool elementCanBeType,
out string fixupReference)
{
- throw new NotImplementedException ();
+ if (ReadNull ())
+ {
+ fixupReference = null;
+ return null;
+ }
+
+ string refid = Reader.GetAttribute ("href");
+
+ if (refid == string.Empty || refid == null)
+ {
+ fixupReference = null;
+
+ XmlQualifiedName qname = GetXsiType ();
+ if (qname == null) qname = new XmlQualifiedName (name, ns);
+
+ if (qname == arrayQName)
+ {
+ delayedListFixups = EnsureHashtable (delayedListFixups);
+ fixupReference = "__<" + delayedListFixups.Count + ">";
+ object items;
+ ReadList (out items);
+ delayedListFixups [fixupReference] = items;
+ return null;
+ }
+ else
+ {
+ WriteCallbackInfo info = GetCallbackInfo (qname);
+ if (info == null)
+ return ReadTypedPrimitive (qname);
+ else
+ return info.Callback();
+ }
+ }
+ else
+ {
+ if (refid.StartsWith ("#")) refid = refid.Substring (1);
+
+ Reader.ReadStartElement ();
+ if (TargetReady (refid))
+ {
+ fixupReference = null;
+ return GetTarget (refid);
+ }
+ else
+ {
+ fixupReference = refid;
+ return null;
+ }
+ }
}
protected IXmlSerializable ReadSerializable (IXmlSerializable serializable)
return (value + reader.ReadString ());
}
- protected object ReadTypedPrimitive (XmlQualifiedName type)
+ protected object ReadTypedPrimitive (XmlQualifiedName qname)
{
- XmlQualifiedName qname = GetXsiType ();
+ if (qname == null) qname = GetXsiType ();
TypeData typeData = TypeTranslator.GetPrimitiveTypeData (qname.Name);
if (typeData == null || typeData.SchemaType != SchemaTypes.Primitive) throw new InvalidOperationException ("Unknown type: " + qname.Name);
return XmlCustomFormatter.FromXmlString (typeData.Type, Reader.ReadElementString ());
[MonoTODO ("Implement")]
protected void Referenced (object o)
{
- throw new NotImplementedException ();
}
protected Array ShrinkArray (Array a, int length, Type elementType, bool isNullable)
}
eventSource.OnUnknownNode (new XmlNodeEventArgs(line_number, line_position, Reader.LocalName, Reader.Name, Reader.NamespaceURI, Reader.NodeType, o, Reader.Value));
- if (Reader.NodeType != XmlNodeType.Attribute)
+ if (Reader.NodeType == XmlNodeType.Attribute)
+ {
+ XmlAttribute att = (XmlAttribute) ReadXmlNode (false);
+ UnknownAttribute (o, att);
+ return;
+ }
+ else if (Reader.NodeType == XmlNodeType.Element)
+ {
+ XmlElement elem = (XmlElement) ReadXmlNode (false);
+ UnknownElement (o, elem);
+ return;
+ }
+ else
{
Reader.Skip();
if (Reader.ReadState == ReadState.EndOfFile)
#endregion // Methods
+ class WriteCallbackInfo
+ {
+ public Type Type;
+ public string TypeName;
+ public string TypeNs;
+ public XmlSerializationReadCallback Callback;
+ }
+
protected class CollectionFixup {
- #region Fields
-
XmlSerializationCollectionFixupCallback callback;
object collection;
object collectionItems;
+ string id;
- #endregion // Fields
-
- #region Constructors
-
- [MonoTODO]
- public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, object collectionItems)
+ public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, string id)
{
this.callback = callback;
this.collection = collection;
- this.collectionItems = collectionItems;
+ this.id = id;
}
- #endregion // Constructors
-
- #region Properties
-
public XmlSerializationCollectionFixupCallback Callback {
get { return callback; }
}
get { return collection; }
}
- public object CollectionItems {
- get { return collectionItems; }
+ public object Id {
+ get { return id; }
}
- #endregion // Properties
+ internal object CollectionItems
+ {
+ get { return collectionItems; }
+ set { collectionItems = value; }
+ }
}
protected class Fixup {
- #region Fields
-
object source;
string[] ids;
XmlSerializationFixupCallback callback;
- #endregion // Fields
-
- #region Constructors
-
- [MonoTODO]
public Fixup (object o, XmlSerializationFixupCallback callback, int count)
{
+ this.source = o;
this.callback = callback;
+ this.ids = new string[count];
}
- [MonoTODO]
public Fixup (object o, XmlSerializationFixupCallback callback, string[] ids)
{
+ this.source = o;
+ this.ids = ids;
this.callback = callback;
}
- #endregion // Constructors
-
- #region Properties
-
public XmlSerializationFixupCallback Callback {
get { return callback; }
}
get { return source; }
set { source = value; }
}
+ }
+
+ protected class CollectionItemFixup \r
+ {
+ Array list;
+ int index;
+ string id;
+
+ public CollectionItemFixup (Array list, int index, string id)
+ {
+ this.list = list;
+ this.index = index;
+ this.id = id;
+ }
+
+ public Array Collection\r
+ {
+ get { return list; }
+ }
+
+ public int Index\r
+ {
+ get { return index; }
+ }
- #endregion // Properties
+ public string Id\r
+ {
+ get { return id; }
+ }
}
+
}
}
public class XmlSerializationReaderInterpreter: XmlSerializationReader
{
XmlMapping _typeMap;
+ SerializationFormat _format;
public XmlSerializationReaderInterpreter(XmlMapping typeMap)
{
_typeMap = typeMap;
+ _format = typeMap.Format;
}
protected override void InitCallbacks ()
{
+ ArrayList maps = _typeMap.RelatedMaps;
+ if (maps != null)
+ {
+ foreach (XmlTypeMapping map in maps) \r
+ {
+ if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
+ {
+ ReaderCallbackInfo info = new ReaderCallbackInfo (this, map);
+ AddReadCallback (map.XmlType, map.Namespace, map.TypeData.Type, new XmlSerializationReadCallback (info.ReadObject));\r
+ }\r
+ }\r
+ }\r
}
protected override void InitIDs ()
{
Reader.MoveToContent();
if (_typeMap is XmlTypeMapping)
- return ReadObject ((XmlTypeMapping)_typeMap, true, true);
+ {
+ if (_format == SerializationFormat.Literal)
+ return ReadObject ((XmlTypeMapping)_typeMap, true, true);
+ else
+ return ReadEncodedObject ((XmlTypeMapping)_typeMap);
+ }
else
return ReadMessage ((XmlMembersMapping)_typeMap);
}
+ object ReadEncodedObject (XmlTypeMapping typeMap)
+ {
+ object ob = null;\r
+ Reader.MoveToContent();\r
+ if (Reader.NodeType == System.Xml.XmlNodeType.Element) \r
+ {\r
+ if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)\r
+ ob = ReadReferencedElement();\r
+ else \r
+ throw CreateUnknownNodeException();\r
+ }\r
+ else \r
+ UnknownNode(null);\r
+\r
+ ReadReferencedElements();\r
+ return ob;\r
+ }
+
object ReadMessage (XmlMembersMapping typeMap)
{
object[] parameters = new object[typeMap.Count];
else
ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true);
+ if (_format == SerializationFormat.Encoded)
+ ReadReferencedElements();\r
+\r
return parameters;
}
{
if (isNullable && ReadNull()) return null;
- if (checkType)
+ if (checkType)
{
System.Xml.XmlQualifiedName t = GetXsiType();
if (t != null)
if (member != null)
{
- SetMemberValue (member, ob, XmlCustomFormatter.FromXmlString (member.TypeData.Type, Reader.Value), isValueList);
+ SetMemberValue (member, ob, GetValueFromXmlString (Reader.Value, member.TypeData, member.MappedType), isValueList);
}
else if (IsXmlnsAttribute(Reader.Name))
{
int[] indexes = null;
object[] flatLists = null;
+ Fixup fixup = null;
if (map.FlatLists != null)
{
if (IsReadOnly (mem, ob, isValueList)) flatLists[mem.FlatArrayIndex] = mem.GetValue (ob);
}
+ if (_format == SerializationFormat.Encoded)
+ {
+ FixupCallbackInfo info = new FixupCallbackInfo (this, map, isValueList);
+ fixup = new Fixup(ob, new XmlSerializationFixupCallback(info.FixupMembers), map.ElementMembers.Count);\r
+ AddFixup (fixup);\r
+ }
+
while (Reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
if (Reader.NodeType == System.Xml.XmlNodeType.Element)
{
if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
{
- if (IsReadOnly (info.Member, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, info.Member.GetValue (ob), false);
- else SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
+ if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
+ {
+ object list = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
+ if (fixup.Ids[info.Member.Index] == null) // Already read\r
+ {
+ if (IsReadOnly (info.Member, ob, isValueList)) throw CreateReadOnlyCollectionException (info.TypeData.FullTypeName);
+ else SetMemberValue (info.Member, ob, list, isValueList);
+ }\r
+ else if (!info.MappedType.TypeData.Type.IsArray)\r
+ {\r
+ if (IsReadOnly (info.Member, ob, isValueList))
+ list = GetMemberValue (info.Member, ob, isValueList);
+ else {
+ list = CreateList (info.MappedType.TypeData.Type);
+ SetMemberValue (info.Member, ob, list, isValueList);
+ }
+ AddFixup (new CollectionFixup (list, new XmlSerializationCollectionFixupCallback (FillList), fixup.Ids[info.Member.Index]));
+ fixup.Ids[info.Member.Index] = null; // The member already has the value, no further fix needed.
+ }\r
+ }
+ else
+ {
+ if (IsReadOnly (info.Member, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, GetMemberValue (info.Member, ob, isValueList), false);
+ else SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
+ }
readFlag[info.Member.Index] = true;
}
else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
}
else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
{
- SetMemberValue (info.Member, ob, ReadObjectElement (info), isValueList);
+ object val;
readFlag[info.Member.Index] = true;
+ if (_format == SerializationFormat.Encoded && info.MultiReferenceType) \r
+ {
+ val = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
+ if (fixup.Ids[info.Member.Index] == null) // already read
+ SetMemberValue (info.Member, ob, val, isValueList);
+ }
+ else
+ SetMemberValue (info.Member, ob, ReadObjectElement (info), isValueList);
}
else
throw new InvalidOperationException ("Unknown member type");
}
}
+ internal void FixupMembers (ClassMap map, object obfixup, bool isValueList)
+ {
+ Fixup fixup = (Fixup)obfixup;
+ ICollection members = map.ElementMembers;
+ string[] ids = fixup.Ids;
+ foreach (XmlTypeMapMember member in members)
+ {
+ if (ids[member.Index] != null)
+ SetMemberValue (member, fixup.Source, GetTarget(ids[member.Index]), isValueList);
+ }
+ }
+
bool IsReadOnly (XmlTypeMapMember member, object ob, bool isValueList)
{
if (isValueList) return false;
else member.SetValue (ob, value);
}
+ object GetMemberValue (XmlTypeMapMember member, object ob, bool isValueList)
+ {
+ if (isValueList) return ((object[])ob)[member.Index];
+ else return member.GetValue (ob);
+ }
+
object ReadObjectElement (XmlTypeMapElementInfo elem)
{
- if (elem.IsPrimitive)
+ switch (elem.TypeData.SchemaType)
{
- if (elem.TypeData.SchemaType == SchemaTypes.XmlNode)
+ case SchemaTypes.XmlNode:
return ReadXmlNode (true);
- else if (elem.IsNullable)
- return XmlCustomFormatter.FromXmlString (elem.TypeData.Type, ReadNullableString ());
- else
- return XmlCustomFormatter.FromXmlString (elem.TypeData.Type, Reader.ReadElementString ());
- }
- else if (elem.MappedType.TypeData.SchemaType == SchemaTypes.Array) {
- return ReadListElement (elem.MappedType, elem.IsNullable, null, true);
- }
- else if (elem.MappedType.TypeData.SchemaType == SchemaTypes.Enum) {
- return GetEnumValue (elem.MappedType, Reader.ReadElementString());
+
+ case SchemaTypes.Primitive:
+ case SchemaTypes.Enum:
+ if (elem.IsNullable) return GetValueFromXmlString (ReadNullableString (), elem.TypeData, elem.MappedType);
+ else return GetValueFromXmlString (Reader.ReadElementString (), elem.TypeData, elem.MappedType);
+
+ case SchemaTypes.Array:
+ return ReadListElement (elem.MappedType, elem.IsNullable, null, true);
+
+ case SchemaTypes.Class:
+ case SchemaTypes.DataSet:
+ return ReadObject (elem.MappedType, elem.IsNullable, true);
+
+ default:
+ throw new NotSupportedException ("Invalid value type");
}
- else
- return ReadObject (elem.MappedType, elem.IsNullable, true);
+ }
+
+ object GetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap)
+ {
+ if (typeData.SchemaType == SchemaTypes.Enum)
+ return GetEnumValue (typeMap, value);
+ else
+ return XmlCustomFormatter.FromXmlString (typeData.Type, value);
}
object ReadListElement (XmlTypeMapping typeMap, bool isNullable, object list, bool canCreateInstance)
return Activator.CreateInstance (listType);
}
+ void FillList (object list, object items)
+ {
+ CopyEnumerableList (items, list);
+ }
+
+ void CopyEnumerableList (object source, object dest)
+ {
+ if (dest == null) throw CreateReadOnlyCollectionException (source.GetType().FullName);
+
+ object[] param = new object[1];
+ MethodInfo mi = dest.GetType().GetMethod ("Add");
+ foreach (object ob in (IEnumerable)source)
+ {
+ param[0] = ob;
+ mi.Invoke (dest, param);
+ }
+ }
+
+ int GetListCount (TypeData listType, object ob)
+ {
+ if (listType.Type.IsArray)
+ return ((Array)ob).Length;
+ else
+ return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
+ }
+
object ReadXmlNodeElement (XmlTypeMapping typeMap, bool isNullable)
{
return ReadXmlNode (false);
EnumMap map = (EnumMap) typeMap.ObjectMap;
return Enum.Parse (typeMap.TypeData.Type, map.GetEnumName (val));
}
+
+ class FixupCallbackInfo
+ {
+ XmlSerializationReaderInterpreter _sri;
+ ClassMap _map;
+ bool _isValueList;
+
+ public FixupCallbackInfo (XmlSerializationReaderInterpreter sri, ClassMap map, bool isValueList)
+ {
+ _sri = sri;
+ _map = map;
+ _isValueList = isValueList;
+ }
+
+ public void FixupMembers (object fixup)
+ {
+ _sri.FixupMembers (_map, fixup, _isValueList);
+ }
+ }
+
+ class ReaderCallbackInfo
+ {
+ XmlSerializationReaderInterpreter _sri;
+ XmlTypeMapping _typeMap;
+
+ public ReaderCallbackInfo (XmlSerializationReaderInterpreter sri, XmlTypeMapping typeMap)
+ {
+ _sri = sri;
+ _typeMap = typeMap;
+ }
+
+ internal object ReadObject ()
+ {
+ return _sri.ReadObject (_typeMap, true, true);
+ }
+ }
}
}
using System.Text;
using System.Xml;
using System.Xml.Schema;
+using System.Runtime.Serialization;
namespace System.Xml.Serialization {
public abstract class XmlSerializationWriter {
#region Fields
- Hashtable references;
- int referenceCount;
+ ObjectIDGenerator idGenerator;
int qnameCount;
ArrayList namespaces;
XmlWriter writer;
+ Queue referencedElements;
+ Hashtable callbacks;
#endregion // Fields
protected XmlSerializationWriter ()
{
qnameCount = 0;
- references = new Hashtable ();
- referenceCount = 0;
}
#endregion // Constructors
throw new NotImplementedException ();
}
- [MonoTODO ("Implement")]
protected void AddWriteCallback (Type type, string typeName, string typeNs, XmlSerializationWriteCallback callback)
{
- throw new NotImplementedException ();
+ WriteCallbackInfo info = new WriteCallbackInfo ();
+ info.Type = type;
+ info.TypeName = typeName;
+ info.TypeNs = typeNs;
+ info.Callback = callback;
+
+ if (callbacks == null) callbacks = new Hashtable ();
+ callbacks.Add (type, info);
}
protected Exception CreateMismatchChoiceException (string value, string elementName, string enumValue)
private string GetId (object o, bool addToReferencesList)
{
- referenceCount += 1;
- string id = String.Format ("id{0}", referenceCount);
- if (addToReferencesList)
- references[o] = id;
- return id;
+ if (idGenerator == null) idGenerator = new ObjectIDGenerator ();
+
+ bool firstTime;
+ long lid = idGenerator.GetId (o, out firstTime);
+ return String.Format ("id{0}", lid);
}
- [MonoTODO ("Need to check for namespace conflicts before blindly allocating qN")]
- private string GetQualifiedName (string name, string ns)
+
+ bool AlreadyQueued (object ob)
{
- string prefix;
+ if (idGenerator == null) return false;
- if (ns == XmlSchema.Namespace)
- prefix = "xsd";
- else
+ bool firstTime;
+ idGenerator.HasId (ob, out firstTime);
+ return !firstTime;
+ }
+
+ private string GetNamespacePrefix (string ns)
+ {
+ string prefix = Writer.LookupPrefix (ns);
+ if (prefix == null) \r
{
- qnameCount += 1;
- prefix = String.Format ("q{0}", qnameCount);
+ prefix = String.Format ("q{0}", ++qnameCount);
WriteAttribute ("xmlns", prefix, null, ns);
}
+ return prefix;
+ }
- return String.Format ("{0}:{1}", prefix, name);
+ [MonoTODO ("Need to check for namespace conflicts before blindly allocating qN")]
+ private string GetQualifiedName (string name, string ns)
+ {
+ return String.Format ("{0}:{1}", GetNamespacePrefix (ns), name);
}
protected abstract void InitCallbacks ();
if (value == null)
return;
- Writer.WriteStartAttribute (prefix, localName, ns);
- WriteValue (value);
- Writer.WriteEndAttribute ();
+ Writer.WriteAttributeString (prefix, localName, ns, value);
}
- [MonoTODO ("Implement")]
protected void WriteElementEncoded (XmlNode node, string name, string ns, bool isNullable, bool any)
{
- throw new NotImplementedException ();
+ if (name != string.Empty)
+ {
+ if (node == null)
+ {
+ if (isNullable)
+ WriteNullTagEncoded (name, ns);
+ }
+ else
+ {
+ Writer.WriteStartElement (name, ns);
+ node.WriteTo (Writer);
+ Writer.WriteEndElement ();
+ }
+ }
+ else
+ node.WriteTo (Writer);
}
- [MonoTODO ("Implement")]
protected void WriteElementLiteral (XmlNode node, string name, string ns, bool isNullable, bool any)
{
if (name != string.Empty)
throw new NotImplementedException ();
}
- [MonoTODO ("Implement")]
protected void WriteNullableStringEncoded (string name, string ns, string value, XmlQualifiedName xsiType)
{
- throw new NotImplementedException ();
+ if (value != null)
+ WriteElementString (name, ns, value, xsiType);
+ else
+ WriteNullTagEncoded (name, ns);
}
[MonoTODO ("Implement")]
throw new NotImplementedException ();
}
- [MonoTODO ("Implement")]
protected void WriteNullableStringLiteral (string name, string ns, string value)
{
if (value != null)
WriteElementString (name, ns, value, null);
else
- {
- WriteStartElement (name, ns);
- WriteAttribute ("xsi","nil", ns, "true");
- WriteEndElement ();
- }
+ WriteNullTagLiteral (name, ns);
}
[MonoTODO ("Implement")]
WriteNullTagEncoded (name, String.Empty);
}
- [MonoTODO ("Implement")]
protected void WriteNullTagEncoded (string name, string ns)
{
- throw new NotImplementedException ();
+ WriteStartElement (name, ns);
+ WriteAttribute ("xsi","null", XmlSchema.InstanceNamespace, "1");
+ WriteEndElement ();
}
protected void WriteNullTagLiteral (string name)
WritePotentiallyReferencingElement (n, ns, o, ambientType, suppressReference, false);
}
- [MonoTODO ("Implement")]
protected void WritePotentiallyReferencingElement (string n, string ns, object o, Type ambientType, bool suppressReference, bool isNullable)
{
- throw new NotImplementedException ();
+ if (o == null)
+ {
+ if (isNullable) WriteNullTagEncoded (n, ns);
+ return;
+ }
+
+ WriteStartElement (n, ns, o, true);
+
+ CheckReferenceQueue ();
+
+ if (callbacks.ContainsKey (o.GetType ()))
+ {
+ WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
+ if (o.GetType ().IsEnum) {
+ info.Callback (o);
+ }
+ else if (suppressReference) {
+ Writer.WriteAttributeString ("id", GetId (o, false));
+ if (ambientType != o.GetType ()) WriteXsiType(info.TypeName, info.TypeNs);
+ info.Callback (o);
+ }
+ else {
+ if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
+ Writer.WriteAttributeString ("href", "#" + GetId (o, true));
+ }
+ }
+ else
+ {
+ // Must be a primitive type
+ TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+ if (td.SchemaType != SchemaTypes.Primitive)
+ throw new InvalidOperationException ("Invalid type: " + o.GetType().FullName);
+ WriteXsiType(td.XmlType, XmlSchema.Namespace);
+ Writer.WriteString (XmlCustomFormatter.ToXmlString (o));
+ }
+
+ WriteEndElement (o);
}
- [MonoTODO ("Implement")]
protected void WriteReferencedElements ()
{
- throw new NotImplementedException ();
+ if (referencedElements == null) return;
+ if (callbacks == null) return;
+
+ while (referencedElements.Count > 0)
+ {
+ object o = referencedElements.Dequeue ();
+ TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+ WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
+ WriteStartElement (info.TypeName, info.TypeNs, o, true);
+ Writer.WriteAttributeString ("id", GetId (o, false));
+
+ if (td.SchemaType != SchemaTypes.Array) // Array use its own "arrayType" attribute
+ WriteXsiType(info.TypeName, info.TypeNs);
+
+ info.Callback (o);
+ WriteEndElement (o);
+ }
}
protected void WriteReferencingElement (string n, string ns, object o)
WriteReferencingElement (n, ns, o, false);
}
- [MonoTODO ("Implement")]
protected void WriteReferencingElement (string n, string ns, object o, bool isNullable)
{
- throw new NotImplementedException ();
+ if (o == null)
+ {
+ if (isNullable) WriteNullTagEncoded (n, ns);
+ return;
+ }
+ else
+ {
+ CheckReferenceQueue ();
+ if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
+
+ Writer.WriteStartElement (n, ns);
+ Writer.WriteAttributeString ("href", "#" + GetId (o, true));
+ Writer.WriteEndElement ();
+ }
}
+ void CheckReferenceQueue ()
+ {
+ if (referencedElements == null) \r
+ {
+ referencedElements = new Queue ();
+ InitCallbacks ();
+ }
+ }
+
+
[MonoTODO ("Implement")]
protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable)
{
{
WriteState oldState = Writer.WriteState;
- if (writePrefixed) {
+ if (writePrefixed && ns != string.Empty) {
name = XmlCustomFormatter.FromXmlName (name);
- Writer.WriteStartElement (String.Empty, name, ns);
+ string prefix = Writer.LookupPrefix (ns);
+ if (prefix == null) prefix = "q" + (++qnameCount);
+ Writer.WriteStartElement (prefix, name, ns);
} else
Writer.WriteStartElement (name, ns);
- if (oldState == WriteState.Prolog) {
+ if ((o == null) || (oldState == WriteState.Prolog && !TypeTranslator.IsPrimitive (o.GetType()))) {
WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);
}
protected void WriteXsiType (string name, string ns)
{
if (ns != null && ns != string.Empty)
- WriteAttribute ("xsi", "type", ns, GetQualifiedName (name, ns));
+ WriteAttribute (GetNamespacePrefix (XmlSchema.InstanceNamespace), "type", ns, GetQualifiedName (name, ns));
else
- WriteAttribute ("xsi", "type", ns, name);
+ WriteAttribute (GetNamespacePrefix (XmlSchema.InstanceNamespace), "type", ns, name);
}
#endregion
+
+ class WriteCallbackInfo
+ {
+ public Type Type;
+ public string TypeName;
+ public string TypeNs;
+ public XmlSerializationWriteCallback Callback;
+ }
}
}
using System;
using System.Collections;
using System.Reflection;
+using System.Xml.Schema;
namespace System.Xml.Serialization
{
internal class XmlSerializationWriterInterpreter: XmlSerializationWriter
{
XmlMapping _typeMap;
+ SerializationFormat _format;
public XmlSerializationWriterInterpreter(XmlMapping typeMap)
{
_typeMap = typeMap;
+ _format = typeMap.Format;
}
protected override void InitCallbacks ()
{
+ ArrayList maps = _typeMap.RelatedMaps;
+ if (maps != null)
+ {
+ foreach (XmlTypeMapping map in maps) {
+ CallbackInfo info = new CallbackInfo (this, map);
+ if (map.TypeData.SchemaType == SchemaTypes.Enum) AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteObject));\r
+ else AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteEnum));\r
+ }\r
+ }\r
}
internal override void WriteObject (object ob)
if (_typeMap is XmlTypeMapping)
{
XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
- WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false);
+ if (_format == SerializationFormat.Literal)
+ WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false, true);
+ else
+ WritePotentiallyReferencingElement (mp.ElementName, mp.Namespace, ob, mp.TypeData.Type, true, false);
}
else if (ob is object[])
WriteMessage ((XmlMembersMapping)_typeMap, (object[]) ob);
else
throw CreateUnknownTypeException (ob);
+
+ WriteReferencedElements ();
}
- void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType)
+ internal void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)
{
if (ob == null)
{
- if (isNullable) WriteNullTagLiteral(element, namesp);
+ if (isNullable)
+ {
+ if (_format == SerializationFormat.Literal) WriteNullTagLiteral(element, namesp);
+ else WriteNullTagEncoded (element, namesp);
+ }
+ return;
+ }
+
+ if (ob is XmlNode)
+ {
+ if (_format == SerializationFormat.Literal) WriteElementLiteral((XmlNode)ob, "", "", true, false);
+ else WriteElementEncoded((XmlNode)ob, "", "", true, false);
return;
}
XmlTypeMapping map = typeMap.GetRealTypeMap (ob.GetType().FullName);
- if (map == null)
+
+ if (map == null)
{
WriteTypedPrimitive (element, namesp, ob, true);
+ return;
}
- else
+
+ if (writeWrappingElem)
{
- if (map != typeMap) needType = true;
- switch (map.TypeData.SchemaType)
- {
- case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp, needType); break;
- case SchemaTypes.Array: WriteListElement (map, ob, element, namesp, needType); break;
- case SchemaTypes.XmlNode: WriteXmlNodeElement (map, ob, element, namesp, needType); break;
- case SchemaTypes.Primitive: WriteTypedPrimitive (element, namesp, ob, needType); break;
- case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp, needType); break;
- }
+ if (map != typeMap || _format == SerializationFormat.Encoded) needType = true;
+ WriteStartElement (element, namesp, ob);
}
+
+ if (needType)
+ WriteXsiType(map.XmlType, map.Namespace);
+
+ switch (map.TypeData.SchemaType)
+ {
+ case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp); break;
+ case SchemaTypes.Array: WriteListElement (map, ob, element, namesp); break;
+ case SchemaTypes.Primitive: WritePrimitiveElement (map, ob, element, namesp); break;
+ case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp); break;
+ }
+
+ if (writeWrappingElem)
+ WriteEndElement (ob);
}
void WriteMessage (XmlMembersMapping membersMap, object[] parameters)
if (membersMap.HasWrapperElement) {
WriteStartDocument();\r
// TopLevelElement();\r
- WriteStartElement(membersMap.ElementName, membersMap.Namespace);\r
+ WriteStartElement(membersMap.ElementName, membersMap.Namespace, (_format == SerializationFormat.Encoded));\r
+\r
+ if (Writer.LookupPrefix (XmlSchema.Namespace) == null)\r
+ WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
+
+ if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)\r
+ WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);\r
}\r
\r
WriteMembers ((ClassMap)membersMap.ObjectMap, parameters, true);\r
WriteEndElement();
}
- void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+ void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
{
- WriteStartElement(element, namesp, ob);
- if (needType)
- WriteXsiType(typeMap.XmlType, typeMap.Namespace);
-
ClassMap map = (ClassMap)typeMap.ObjectMap;
WriteMembers (map, ob, false);
- WriteEndElement (ob);
}
void WriteMembers (ClassMap map, object ob, bool isValueList)
{
foreach (XmlTypeMapMemberAttribute attr in attributes) {
if (MemberHasValue (attr, ob, isValueList))
- WriteAttribute(attr.AttributeName, attr.Namespace, XmlCustomFormatter.ToXmlString (GetMemberValue (attr, ob, isValueList)));
+ WriteAttribute (attr.AttributeName, attr.Namespace, GetStringValue (attr.MappedType, GetMemberValue (attr, ob, isValueList)));
}
}
if (extraAtts != null) \r
{
foreach (XmlAttribute attr in extraAtts)
- WriteAttribute(attr.LocalName, attr.NamespaceURI, attr.Value);
+ WriteAttribute (attr.LocalName, attr.NamespaceURI, attr.Value);
}
}
if (memType == typeof(XmlTypeMapMemberList))
{
if (memberValue != null) \r
- {
- XmlTypeMapMemberList mm = (XmlTypeMapMemberList)member;
- WriteStartElement(mm.ElementName, mm.Namespace, memberValue);
- WriteListContent (member.TypeData, (ListMap) mm.ListTypeMapping.ObjectMap, memberValue);
- WriteEndElement (memberValue);
- }
+ WriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
}
else if (memType == typeof(XmlTypeMapMemberFlatList))
{
void WriteMemberElement (XmlTypeMapElementInfo elem, object memberValue)
{
- if (elem.IsPrimitive)
+ switch (elem.TypeData.SchemaType)
{
- if (elem.TypeData.SchemaType == SchemaTypes.XmlNode)
- WriteElementLiteral(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
- else if (elem.IsNullable)
- WriteNullableStringLiteral (elem.ElementName, elem.Namespace, XmlCustomFormatter.ToXmlString (memberValue));
- else
- WriteElementString (elem.ElementName, elem.Namespace, XmlCustomFormatter.ToXmlString (memberValue));
+ case SchemaTypes.XmlNode:
+ if (_format == SerializationFormat.Literal) WriteElementLiteral(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
+ else WriteElementEncoded(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
+ break;
+
+ case SchemaTypes.Enum:
+ case SchemaTypes.Primitive:
+ if (_format == SerializationFormat.Literal) {
+ if (elem.IsNullable) WriteNullableStringLiteral (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue));\r
+ else WriteElementString (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue));\r
+ }
+ else {
+ if (elem.IsNullable) WriteNullableStringEncoded (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue), new XmlQualifiedName (elem.DataType, elem.DataTypeNamespace));\r
+ else WriteElementString (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue), new XmlQualifiedName (elem.DataType, elem.DataTypeNamespace));\r
+ }
+ break;
+
+ case SchemaTypes.Array:
+ if (elem.MappedType.MultiReferenceType)
+ WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
+ else {
+ WriteStartElement(elem.ElementName, elem.Namespace, memberValue);
+ WriteListContent (elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue);
+ WriteEndElement (memberValue);
+ }
+ break;
+
+ case SchemaTypes.Class:
+ if (elem.MappedType.MultiReferenceType) {
+ if (elem.MappedType.TypeData.Type == typeof(object))
+ WritePotentiallyReferencingElement (elem.ElementName, elem.Namespace, memberValue, null, false, elem.IsNullable);
+ else
+ WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
+ }
+ else WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false, true);
+ break;
+
+ case SchemaTypes.DataSet:
+ throw new NotSupportedException ("Invalid type");
+
+ default:
+ throw new NotSupportedException ("Invalid value type");
}
- else if (elem.TypeData.SchemaType == SchemaTypes.Enum)
- WriteElementString(elem.ElementName, elem.Namespace, GetEnumXmlValue (elem.MappedType, memberValue));\r
- else
- WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false);
}
- void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+ void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
{
- WriteStartElement(element, namesp, ob);
- if (needType)
- WriteXsiType(typeMap.XmlType, typeMap.Namespace);
-
+ if (_format == SerializationFormat.Encoded)
+ {
+ string n, ns;
+ int itemCount = GetListCount (typeMap.TypeData, ob);
+ ((ListMap) typeMap.ObjectMap).GetArrayType (itemCount, out n, out ns);
+ string arrayType = (ns != string.Empty) ? FromXmlQualifiedName (new XmlQualifiedName(n,ns)) : n;
+ WriteAttribute ("arrayType", SoapReflectionImporter.EncodingNamespace, arrayType);
+ }
WriteListContent (typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob);
- WriteEndElement (ob);
}
void WriteListContent (TypeData listType, ListMap map, object ob)
throw new Exception ("Unsupported collection type");
}
+ int GetListCount (TypeData listType, object ob)
+ {
+ if (listType.Type.IsArray)
+ return ((Array)ob).Length;
+ else
+ return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
+ }
+
void WriteAnyElementContent (XmlTypeMapMemberAnyElement member, object memberValue)
{
if (member.TypeData.Type == typeof (XmlElement)) {
if (elem is XmlElement)
{
if (member.IsElementDefined (elem.Name, elem.NamespaceURI))
- WriteElementLiteral(elem, "", "", false, true);
+ {
+ if (_format == SerializationFormat.Literal) WriteElementLiteral (elem, "", "", false, true);
+ else WriteElementEncoded (elem, "", "", false, true);
+ }
else
throw CreateUnknownAnyElementException (elem.Name, elem.NamespaceURI);
}
}
}
- void WriteXmlNodeElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+ void WritePrimitiveElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
{
- WriteElementLiteral((XmlNode)ob, "", "", true, false);
+ Writer.WriteString (GetStringValue (typeMap, ob));
}
- void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+ void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
{
- Writer.WriteStartElement(element, namesp);\r
- if (needType) WriteXsiType(typeMap.XmlType, typeMap.Namespace);\r
Writer.WriteString (GetEnumXmlValue (typeMap, ob));\r
- Writer.WriteEndElement();
+ }
+
+ string GetStringValue (XmlTypeMapping typeMap, object value)
+ {
+ if (typeMap != null && typeMap.TypeData.SchemaType == SchemaTypes.Enum)
+ return GetEnumXmlValue (typeMap, value);
+ else
+ return XmlCustomFormatter.ToXmlString (value);
}
string GetEnumXmlValue (XmlTypeMapping typeMap, object ob)
EnumMap map = (EnumMap)typeMap.ObjectMap;
return map.GetXmlName (ob.ToString ());
}
+
+ class CallbackInfo
+ {
+ XmlSerializationWriterInterpreter _swi;
+ XmlTypeMapping _typeMap;
+
+ public CallbackInfo (XmlSerializationWriterInterpreter swi, XmlTypeMapping typeMap)
+ {
+ _swi = swi;
+ _typeMap = typeMap;
+ }
+
+ internal void WriteObject (object ob)
+ {
+ _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, true, false);
+ }
+
+ internal void WriteEnum (object ob)
+ {
+ _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, false, false);
+ }
+ }
+
}
}
set { _dataType = value; }
}
+ public string DataTypeNamespace
+ {
+ get
+ {
+ if (_mappedType == null) return XmlSchema.Namespace;
+ else return _mappedType.Namespace;
+ }
+ }
+
public XmlSchemaForm Form
{
get { return _form; }
set { _nestingLevel = value; }
}
+ internal bool MultiReferenceType\r
+ {\r
+ get \r
+ { \r
+ if (_mappedType != null) return _mappedType.MultiReferenceType;\r
+ else return false;\r
+ }\r
+ }\r
+\r
public override bool Equals (object other)
{
XmlTypeMapElementInfo oinfo = (XmlTypeMapElementInfo)other;
string _dataType;
string _namespace = "";
XmlSchemaForm _form;
+ XmlTypeMapping _mappedType;
public XmlTypeMapMemberAttribute()
{
get { return _form; }
set { _form = value; }
}
+
+ public XmlTypeMapping MappedType
+ {
+ get { return _mappedType; }
+ set { _mappedType = value; }
+ }
}
}
}
else
{
+ if (memberValue == null)
+ return (XmlTypeMapElementInfo) _elementInfo[0];
Type type = memberValue.GetType();
foreach (XmlTypeMapElementInfo elem in _elementInfo)
if (elem.TypeData.Type == type) return elem;
internal class XmlTypeMapMemberList : XmlTypeMapMemberElement
{
- XmlTypeMapping _listMap;
- string _elementName;
- string _namespace;
-
public XmlTypeMapping ListTypeMapping
{
- get { return _listMap; }
- set { _listMap = value; }
+ get { return ((XmlTypeMapElementInfo) ElementInfo[0]).MappedType; }
}
public string ElementName
{
- get { return _elementName; }
- set { _elementName = value; }
+ get { return ((XmlTypeMapElementInfo) ElementInfo[0]).ElementName; }
}
public string Namespace
{
- get { return _namespace; }
- set { _namespace = value; }
+ get { return ((XmlTypeMapElementInfo) ElementInfo[0]).Namespace; }
}
}
private string ns;\r
private string xmlType;\r
TypeData type;\r
+ bool multiReferenceType = false;\r
\r
ArrayList _derivedTypes = new ArrayList();\r
\r
set { _derivedTypes = value; }\r
}\r
\r
+ internal bool MultiReferenceType\r
+ {\r
+ get { return multiReferenceType; }\r
+ set { multiReferenceType = value; }\r
+ }\r
+\r
internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
{\r
// Returns the map for a subtype of this map's type\r
return null;\r
}\r
\r
+ public void GetArrayType (int itemCount, out string localName, out string ns)\r
+ {\r
+ string arrayDim;\r
+ if (itemCount != -1) arrayDim = "[" + itemCount + "]";\r
+ else arrayDim = "[]";\r
+\r
+ XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];\r
+ if (info.TypeData.SchemaType == SchemaTypes.Array)\r
+ {\r
+ string nm;\r
+ ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);\r
+ localName = nm + arrayDim;\r
+ }\r
+ else \r
+ {\r
+ if (info.MappedType != null)\r
+ {\r
+ localName = info.MappedType.XmlType + arrayDim;\r
+ ns = info.MappedType.Namespace;\r
+ }\r
+ else \r
+ {\r
+ localName = info.DataType + arrayDim;\r
+ ns = info.DataTypeNamespace;\r
+ }\r
+ }\r
+ }\r
+\r
public override bool Equals (object other)\r
{\r
ListMap lmap = other as ListMap;\r