//
using System.Collections;
+using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Xml.Schema;
string ns,
XmlReflectionMember[] members,
bool hasWrapperElement,
- bool writeAccessors)
+ bool rpc)
{
- return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, true);
+ return ImportMembersMapping (elementName, ns, members, hasWrapperElement, rpc, true);
}
#if NET_2_0
string ns,
XmlReflectionMember[] members,
bool hasWrapperElement,
- bool writeAccessors,
- bool validate)
+ bool rpc,
+ bool openModel)
{
- return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, validate, XmlMappingAccess.Read | XmlMappingAccess.Write);
+ return ImportMembersMapping (elementName, ns, members, hasWrapperElement, rpc, openModel, XmlMappingAccess.Read | XmlMappingAccess.Write);
}
#if NET_2_0
- [MonoTODO ("writeAccessors, validate, mapping access")]
+ [MonoTODO] // FIXME: handle writeAccessors, validate, and mapping access
public
#endif
XmlMembersMapping ImportMembersMapping (string elementName,
string ns,
XmlReflectionMember[] members,
bool hasWrapperElement,
- bool writeAccessors,
- bool validate,
+ bool rpc,
+ bool openModel,
XmlMappingAccess access)
{
// Reset (); Disabled. See ChangeLog
- XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
+ ArrayList mapping = new ArrayList ();
for (int n=0; n<members.Length; n++)
{
XmlTypeMapMember mapMem = CreateMapMember (null, members[n], ns);
- mapping[n] = new XmlMemberMapping (members[n].MemberName, ns, mapMem, false);
+ mapMem.GlobalIndex = n;
+ mapMem.CheckOptionalValueType (members);
+ mapping.Add (new XmlMemberMapping (members[n].MemberName, ns, mapMem, false));
}
elementName = XmlConvert.EncodeLocalName (elementName);
- XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, mapping);
+ XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, (XmlMemberMapping[])mapping.ToArray (typeof(XmlMemberMapping)));
mps.RelatedMaps = relatedMaps;
mps.Format = SerializationFormat.Literal;
Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
+#if !NET_2_1
mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, extraTypes);
if (allowPrivateTypes) mps.Source.CanBeGenerated = false;
+#endif
return mps;
}
return ImportTypeMapping (type, null, defaultNamespace);
}
- public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute group)
+ public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute root)
{
- return ImportTypeMapping (type, group, null);
+ return ImportTypeMapping (type, root, null);
}
public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
default: throw new NotSupportedException ("Type " + typeData.Type.FullName + " not supported for XML stialization");
}
+#if NET_2_0
+ // bug #372780
+ map.SetKey (typeData.Type.ToString ());
+#endif
map.RelatedMaps = relatedMaps;
map.Format = SerializationFormat.Literal;
Type[] extraTypes = includedTypes != null ? (Type[]) includedTypes.ToArray (typeof (Type)) : null;
+#if !NET_2_1
map.Source = new XmlTypeSerializationSource (typeData.Type, root, attributeOverrides, defaultNamespace, extraTypes);
if (allowPrivateTypes) map.Source.CanBeGenerated = false;
+#endif
return map;
} catch (InvalidOperationException ex) {
throw new InvalidOperationException (string.Format (CultureInfo.InvariantCulture,
string elementName;
bool includeInSchema = true;
XmlAttributes atts = null;
- bool nullable = true;
+ bool nullable = CanBeNull (typeData);
if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
if (atts.XmlType != null)
{
- if (atts.XmlType.Namespace != null && typeData.SchemaType != SchemaTypes.Enum)
+ if (atts.XmlType.Namespace != null)
typeNamespace = atts.XmlType.Namespace;
if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
XmlTypeMapping map;
switch (typeData.SchemaType) {
case SchemaTypes.XmlSerializable:
- map = new XmlSerializableMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
+ map = new XmlSerializableMapping (root, elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
break;
case SchemaTypes.Primitive:
if (!typeData.IsXsdType)
ClassMap classMap = new ClassMap ();
map.ObjectMap = classMap;
- ICollection members = GetReflectionMembers (type);
+ var members = GetReflectionMembers (type);
+ bool? isOrderExplicit = null;
+ foreach (XmlReflectionMember rmember in members)
+ {
+ int? order = rmember.XmlAttributes.Order;
+ if (isOrderExplicit == null)
+ {
+ if (order != null)
+ isOrderExplicit = (int) order >= 0;
+ }
+ else if (order != null && isOrderExplicit != ((int) order >= 0))
+ throw new InvalidOperationException ("Inconsistent XML sequence was detected. If there are XmlElement/XmlArray/XmlAnyElement attributes with explicit Order, then every other member must have an explicit order too.");
+ }
+ if (isOrderExplicit == true)
+ members.Sort ((m1, m2) => (int) m1.XmlAttributes.SortableOrder - (int) m2.XmlAttributes.SortableOrder);
+
foreach (XmlReflectionMember rmember in members)
{
string ns = map.XmlTypeNamespace;
XmlTypeMapMember mem = classMap.XmlTextCollector;
if (mem.TypeData.Type != typeof(string) &&
mem.TypeData.Type != typeof(string[]) &&
- mem.TypeData.Type != typeof(object[]) &&
- mem.TypeData.Type != typeof(XmlNode[]))
+#if !MOONLIGHT
+ mem.TypeData.Type != typeof(XmlNode[]) &&
+#endif
+ mem.TypeData.Type != typeof(object[]))
throw new InvalidOperationException (String.Format (errSimple2, map.TypeData.TypeName, mem.Name, mem.TypeData.TypeName));
}
foreach (XmlArrayItemAttribute att in atts.XmlArrayItems)
{
+ if (att.Namespace != null && att.Form == XmlSchemaForm.Unqualified)
+ throw new InvalidOperationException ("XmlArrayItemAttribute.Form must not be Unqualified when it has an explicit Namespace value.");
if (att.NestingLevel != nestingLevel) continue;
Type elemType = (att.Type != null) ? att.Type : itemType;
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData(elemType, att.DataType));
elem.Namespace = att.Namespace != null ? att.Namespace : defaultNamespace;
if (elem.Namespace == null) elem.Namespace = "";
elem.Form = att.Form;
+ if (att.Form == XmlSchemaForm.Unqualified)
+ elem.Namespace = string.Empty;
elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData);
elem.NestingLevel = att.NestingLevel;
helper.RegisterClrType (map, type, map.XmlTypeNamespace);
return map;
}
-
+#if MOONLIGHT
+ // Enum.GetNames is not available in SL API
+ public static System.Collections.Generic.IEnumerable<string> GetEnumNames (Type type)
+ {
+ System.Collections.Generic.List<string> names = new System.Collections.Generic.List<string> ();
+ foreach (FieldInfo fi in type.GetFields (BindingFlags.Static | BindingFlags.Public))
+ names.Add (fi.Name);
+ return names;
+ }
+#endif
XmlTypeMapping ImportEnumMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
{
Type type = typeData.Type;
map.IsNullable = false;
helper.RegisterClrType (map, type, map.XmlTypeNamespace);
- string [] names = Enum.GetNames (type);
ArrayList members = new ArrayList();
- foreach (string name in names)
- {
+#if MOONLIGHT
+ foreach (string name in GetEnumNames (type)) {
+#else
+ string [] names = Enum.GetNames (type);
+ foreach (string name in names) {
+#endif
FieldInfo field = type.GetField (name);
string xmlName = null;
if (field.IsDefined(typeof(XmlIgnoreAttribute), false))
}
}
- ICollection GetReflectionMembers (Type type)
+ List<XmlReflectionMember> GetReflectionMembers (Type type)
{
// First we want to find the inheritance hierarchy in reverse order.
Type currentType = type;
propList.Insert(currentIndex++, prop);
}
#endif
- ArrayList members = new ArrayList();
+ var members = new List<XmlReflectionMember>();
int fieldIndex=0;
int propIndex=0;
// We now step through the type hierarchy from the base (object) through
XmlAttributes atts = attributeOverrides[type, prop.Name];
if (atts == null) atts = new XmlAttributes (prop);
if (atts.XmlIgnore) continue;
- if (!prop.CanWrite && (TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array || prop.PropertyType.IsArray)) continue;
+ if (!prop.CanWrite) {
+ if (prop.PropertyType.IsGenericType && TypeData.GetGenericListItemType (prop.PropertyType) == null) continue; // check this before calling GetTypeData() which raises error for missing Add(). See bug #704813.
+ if (TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array || prop.PropertyType.IsArray) continue;
+ }
XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
member.DeclaringType = prop.DeclaringType;
members.Add(member);
else break;
}
}
- return members;
+
+ return members;
}
private XmlTypeMapMember CreateMapMember (Type declaringType, XmlReflectionMember rmember, string defaultNamespace)
XmlAttributes atts = rmember.XmlAttributes;
TypeData typeData = TypeTranslator.GetTypeData (rmember.MemberType);
+ if (atts.XmlArray != null) {
+ if (atts.XmlArray.Namespace != null && atts.XmlArray.Form == XmlSchemaForm.Unqualified)
+ throw new InvalidOperationException ("XmlArrayAttribute.Form must not be Unqualified when it has an explicit Namespace value.");
+ if (typeData.SchemaType != SchemaTypes.Array &&
+ !(typeData.SchemaType == SchemaTypes.Primitive && typeData.Type == typeof (byte [])))
+ throw new InvalidOperationException ("XmlArrayAttribute can be applied to members of array or collection type.");
+ }
+
+#if !MOONLIGHT
if (atts.XmlAnyAttribute != null)
{
if ( (rmember.MemberType.FullName == "System.Xml.XmlAttribute[]") ||
else
throw new InvalidOperationException ("XmlAnyAttributeAttribute can only be applied to members of type XmlAttribute[] or XmlNode[]");
}
- else if (atts.XmlAnyElements != null && atts.XmlAnyElements.Count > 0)
+ else
+#endif
+ if (atts.XmlAnyElements != null && atts.XmlAnyElements.Count > 0)
{
- if ( (rmember.MemberType.FullName == "System.Xml.XmlElement[]") ||
- (rmember.MemberType.FullName == "System.Xml.XmlNode[]") ||
- (rmember.MemberType.FullName == "System.Xml.XmlElement"))
- {
- XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
- member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
- mapMember = member;
- }
- else
- throw new InvalidOperationException ("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]");
+ // no XmlNode type check is done here (seealso: bug #553032).
+ XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
+ member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
+ mapMember = member;
}
else if (atts.Xmlns)
{
mapAttribute.AttributeName = XmlConvert.EncodeLocalName (mapAttribute.AttributeName);
if (typeData.IsComplexType)
- mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
-
+ mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, defaultNamespace);
+
if (atts.XmlAttribute.Namespace != null && atts.XmlAttribute.Namespace != defaultNamespace)
{
if (atts.XmlAttribute.Form == XmlSchemaForm.Unqualified)
{
// A flat list
- // TODO: check that it does not have XmlArrayAttribute
+ // check that it does not have XmlArrayAttribute
+ if (atts.XmlArray != null)
+ throw new InvalidOperationException ("XmlArrayAttribute cannot be used with members which also attributed with XmlElementAttribute or XmlTextAttribute.");
+
XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
member.ListMap = new ListMap ();
member.ListMap.ItemInfo = ImportElementInfo (declaringType, XmlConvert.EncodeLocalName (rmember.MemberName), defaultNamespace, typeData.ListItemType, member, atts);
member.ElementInfo = new XmlTypeMapElementInfoList();
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, typeData);
elem.ElementName = XmlConvert.EncodeLocalName((atts.XmlArray != null && atts.XmlArray.ElementName.Length != 0) ? atts.XmlArray.ElementName : rmember.MemberName);
+ // note that it could be changed below (when Form is Unqualified)
elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
elem.IsNullable = (atts.XmlArray != null) ? atts.XmlArray.IsNullable : false;
elem.Form = (atts.XmlArray != null) ? atts.XmlArray.Form : XmlSchemaForm.Qualified;
+ elem.ExplicitOrder = (atts.XmlArray != null) ? atts.XmlArray.Order : -1;
+ // This is a bit tricky, but is done
+ // after filling descendant members, so
+ // that array items could be serialized
+ // with proper namespace.
+ if (atts.XmlArray != null && atts.XmlArray.Form == XmlSchemaForm.Unqualified)
+ elem.Namespace = String.Empty;
member.ElementInfo.Add (elem);
mapMember = member;
Type choiceEnumType = null;
XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
- ImportTextElementInfo (list, defaultType, member, atts);
+ ImportTextElementInfo (list, defaultType, member, atts, defaultNamespace);
if (atts.XmlChoiceIdentifier != null) {
if (cls == null)
if (elem.Form != XmlSchemaForm.Unqualified)
elem.Namespace = (att.Namespace != null) ? att.Namespace : defaultNamespace;
elem.IsNullable = att.IsNullable;
-
- if (elem.IsNullable && elem.TypeData.IsValueType)
+ elem.ExplicitOrder = att.Order;
+
+ if (elem.IsNullable && !elem.TypeData.IsNullable)
throw new InvalidOperationException ("IsNullable may not be 'true' for value type " + elem.TypeData.FullTypeName + " in member '" + defaultName + "'");
if (elem.TypeData.IsComplexType)
+ " enumeration value '{1}' for element '{1} from"
+ " namespace '{2}'.", choiceEnumType, elem.ElementName,
elem.Namespace));
- elem.ChoiceValue = Enum.Parse (choiceEnumType, cname);
+ elem.ChoiceValue = Enum.Parse (choiceEnumType, cname, false);
}
list.Add (elem);
{
XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
- ImportTextElementInfo (list, rmember.MemberType, member, atts);
+ ImportTextElementInfo (list, rmember.MemberType, member, atts, defaultNamespace);
+#if !MOONLIGHT // no practical anyElement support
foreach (XmlAnyElementAttribute att in atts.XmlAnyElements)
{
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
if (att.Namespace != null)
throw new InvalidOperationException ("The element " + rmember.MemberName + " has been attributed with an XmlAnyElementAttribute and a namespace '" + att.Namespace + "', but no name. When a namespace is supplied, a name is also required. Supply a name or remove the namespace.");
}
+ elem.ExplicitOrder = att.Order;
list.Add (elem);
}
+#endif
return list;
}
- void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
+ void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts, string defaultNamespace)
{
if (atts.XmlText != null)
{
}
defaultType = atts.XmlText.Type;
}
+#if !MOONLIGHT
if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText); // Nodes must be text nodes
+#endif
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
)
throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
+ if (elem.TypeData.IsComplexType)
+ elem.MappedType = ImportTypeMapping (defaultType, null, defaultNamespace);
elem.IsTextElement = true;
elem.WrappedElement = false;
list.Add (elem);
bool CanBeNull (TypeData type)
{
- return (type.SchemaType != SchemaTypes.Primitive || type.Type == typeof (string));
+#if !NET_2_0 // idiotic compatibility
+ if (type.Type == typeof (XmlQualifiedName))
+ return false;
+#endif
+ return !type.Type.IsValueType || type.IsNullable;
}
public void IncludeType (Type type)
if (defaultValue == DBNull.Value || typeData.SchemaType != SchemaTypes.Enum)
return defaultValue;
+#if MOONLIGHT
+ string namedValue = (defaultValue as Enum).ToString ("g");
+ string decimalValue = (defaultValue as Enum).ToString ("d");
+#else
// get string representation of enum value
string namedValue = Enum.Format (typeData.Type, defaultValue, "g");
// get decimal representation of enum value
string decimalValue = Enum.Format (typeData.Type, defaultValue, "d");
-
+#endif
// if decimal representation matches string representation, then
// the value is not defined in the enum type (as the "g" format
// will return the decimal equivalent of the value if the value