using System.Reflection;
using System.Collections;
+using System.Xml.Schema;
namespace System.Xml.Serialization {
public class XmlReflectionImporter {
ArrayList includedTypes;
ReflectionHelper helper = new ReflectionHelper();
int arrayChoiceCount = 1;
+ ArrayList relatedMaps = new ArrayList ();
+ bool allowPrivateTypes = false;
+
+ static readonly string errSimple = "Cannot serialize object of type '{0}'. Base " +
+ "type '{1}' has simpleContent and can be only extended by adding XmlAttribute " +
+ "elements. Please consider changing XmlText member of the base class to string array";
+
+ static readonly string errSimple2 = "Cannot serialize object of type '{0}'. " +
+ "Consider changing type of XmlText member '{1}' from '{2}' to string or string array";
#region Constructors
helper = new ReflectionHelper();
arrayChoiceCount = 1;
}
+
+ internal bool AllowPrivateTypes
+ {
+ get { return allowPrivateTypes; }
+ set { allowPrivateTypes = value; }
+ }
#endregion // Constructors
for (int n=0; n<members.Length; n++)
{
XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
- mapping[n] = new XmlMemberMapping (members[n], mapMem);
+ mapping[n] = new XmlMemberMapping (members[n].MemberName, ns, mapMem, false);
}
- XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+ XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, mapping);
+ mps.RelatedMaps = relatedMaps;
mps.Format = SerializationFormat.Literal;
+ mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, includedTypes);
+ if (allowPrivateTypes) mps.Source.CanBeGenerated = false;
return mps;
}
default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
}
+ map.RelatedMaps = relatedMaps;
map.Format = SerializationFormat.Literal;
+ map.Source = new XmlTypeSerializationSource (type, root, attributeOverrides, defaultNamespace, includedTypes);
+ if (allowPrivateTypes) map.Source.CanBeGenerated = false;
return map;
}
XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
{
- string membersNamespace = defaultNamespace;
+ string rootNamespace = defaultNamespace;
+ string typeNamespace = null;
+
string elementName;
+ bool includeInSchema = true;
XmlAttributes atts = null;
if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
if (atts.XmlType != null)
{
- if (atts.XmlType.Namespace != null && atts.XmlType.Namespace != string.Empty)
- membersNamespace = atts.XmlType.Namespace;
+ if (atts.XmlType.Namespace != null && atts.XmlType.Namespace != string.Empty && typeData.SchemaType != SchemaTypes.Enum)
+ typeNamespace = atts.XmlType.Namespace;
if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
defaultXmlType = atts.XmlType.TypeName;
+
+ includeInSchema = atts.XmlType.IncludeInSchema;
}
elementName = defaultXmlType;
if (root.ElementName != null && root.ElementName != String.Empty)
elementName = root.ElementName;
if (root.Namespace != null && root.Namespace != String.Empty)
- membersNamespace = root.Namespace;
+ rootNamespace = root.Namespace;
}
- if (membersNamespace == null) membersNamespace = "";
- XmlTypeMapping map = new XmlTypeMapping (elementName, membersNamespace, typeData, defaultXmlType);
+ if (rootNamespace == null) rootNamespace = "";
+ if (typeNamespace == null || typeNamespace.Length == 0) typeNamespace = rootNamespace;
+
+ XmlTypeMapping map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
+ map.IncludeInSchema = includeInSchema;
+ relatedMaps.Add (map);
+
return map;
}
XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
TypeData typeData = TypeTranslator.GetTypeData (type);
- XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
if (map != null) return map;
- map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+ if (!allowPrivateTypes)
+ ReflectionHelper.CheckSerializableType (type);
- helper.RegisterClrType (map, type, defaultNamespace);
- helper.RegisterSchemaType (map, map.XmlType, defaultNamespace);
+ map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+ helper.RegisterClrType (map, type, map.XmlTypeNamespace);
+ helper.RegisterSchemaType (map, map.XmlType, map.XmlTypeNamespace);
+
+ // Import members
ClassMap classMap = new ClassMap ();
map.ObjectMap = classMap;
- // Import members
-
// try
// {
ICollection members = GetReflectionMembers (type);
foreach (XmlReflectionMember rmember in members)
{
if (rmember.XmlAttributes.XmlIgnore) continue;
- classMap.AddMember (CreateMapMember (rmember, map.Namespace));
+ XmlTypeMapMember mem = CreateMapMember (rmember, map.XmlTypeNamespace);
+ mem.CheckOptionalValueType (type);
+ classMap.AddMember (mem);
}
// }
// catch (Exception ex) {
// throw helper.CreateError (map, ex.Message);
// }
- // Import derived classes
-
- XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), 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 + "'");
-
- XmlTypeMapping derived = ImportTypeMapping (includedType, root, defaultNamespace);
- map.DerivedTypes.Add (derived);
- if (type != typeof (object)) derived.BaseMap = map;
- map.DerivedTypes.AddRange (derived.DerivedTypes);
- }
+ ImportIncludedTypes (type, defaultNamespace);
+
+ // Import extra classes
if (type == typeof (object) && includedTypes != null)
{
map.DerivedTypes.Add (ImportTypeMapping (intype, defaultNamespace));
}
- // Register this map as a derived class of object
+ // Register inheritance relations
- if (typeData.Type != typeof(object))
- ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+ if (type.BaseType != null)
+ {
+ XmlTypeMapping bmap = ImportClassMapping (type.BaseType, root, defaultNamespace);
+
+ if (type.BaseType != typeof (object)) {
+ map.BaseMap = bmap;
+ classMap.SetCanBeSimpleType (false);
+ }
+
+ // At this point, derived classes of this map must be already registered
+
+ RegisterDerivedMap (bmap, map);
+
+ if (((ClassMap)bmap.ObjectMap).HasSimpleContent && classMap.ElementMembers != null && classMap.ElementMembers.Count != 1)
+ throw new InvalidOperationException (String.Format (errSimple, map.TypeData.TypeName, map.BaseMap.TypeData.TypeName));
+ }
+
+ if (classMap.XmlTextCollector != null && !classMap.HasSimpleContent)
+ {
+ 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[]))
+
+ throw new InvalidOperationException (String.Format (errSimple2, map.TypeData.TypeName, mem.Name, mem.TypeData.TypeName));
+ }
return map;
}
+
+ void RegisterDerivedMap (XmlTypeMapping map, XmlTypeMapping derivedMap)
+ {
+ map.DerivedTypes.Add (derivedMap);
+ map.DerivedTypes.AddRange (derivedMap.DerivedTypes);
+
+ if (map.BaseMap != null)
+ RegisterDerivedMap (map.BaseMap, derivedMap);
+ else {
+ XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
+ if (obmap != map)
+ obmap.DerivedTypes.Add (derivedMap);
+ }
+ }
+
+ string GetTypeNamespace (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
+ {
+ string typeNamespace = null;
+
+ XmlAttributes atts = null;
+ if (!typeData.IsListType)
+ {
+ if (attributeOverrides != null)
+ atts = attributeOverrides[typeData.Type];
+ }
+
+ if (atts == null)
+ atts = new XmlAttributes (typeData.Type);
+
+ if (atts.XmlType != null)
+ {
+ if (atts.XmlType.Namespace != null && atts.XmlType.Namespace.Length != 0 && typeData.SchemaType != SchemaTypes.Enum)
+ typeNamespace = atts.XmlType.Namespace;
+ }
+
+ if (typeNamespace != null && typeNamespace.Length != 0) return typeNamespace;
+
+ if (atts.XmlRoot != null && root == null)
+ root = atts.XmlRoot;
+
+ if (root != null)
+ {
+ if (root.Namespace != null && root.Namespace.Length != 0)
+ return root.Namespace;
+ }
+ if (defaultNamespace == null) return "";
+ else return defaultNamespace;
+ }
XmlTypeMapping ImportListMapping (Type type, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
{
TypeData typeData = TypeTranslator.GetTypeData (type);
ListMap obmap = new ListMap ();
+ if (!allowPrivateTypes)
+ ReflectionHelper.CheckSerializableType (type);
+
if (atts == null) atts = new XmlAttributes();
Type itemType = typeData.ListItemType;
elem.Namespace = att.Namespace != null ? att.Namespace : defaultNamespace;
if (elem.Namespace == null) elem.Namespace = "";
elem.Form = att.Form;
- elem.IsNullable = att.IsNullable;
+ elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData);
elem.NestingLevel = att.NestingLevel;
if (isMultiArray)
else if (elem.TypeData.IsComplexType)
elem.MappedType = ImportTypeMapping (itemType, null, defaultNamespace);
- if (elem.MappedType != null) elem.ElementName = elem.MappedType.ElementName;
+ if (elem.MappedType != null) elem.ElementName = elem.MappedType.XmlType;
else elem.ElementName = TypeTranslator.GetTypeData(itemType).XmlType ;
elem.Namespace = (defaultNamespace != null) ? defaultNamespace : "";
- elem.IsNullable = false;
+ elem.IsNullable = CanBeNull (elem.TypeData);
list.Add (elem);
}
else
{
XmlTypeMapElementInfo elem = ((XmlTypeMapElementInfo)list[0]);
- if (elem.MappedType != null) baseName = GetArrayName (elem.MappedType.ElementName);
- else baseName = GetArrayName (elem.ElementName);
+ if (elem.MappedType != null) baseName = TypeTranslator.GetArrayName (elem.MappedType.XmlType);
+ else baseName = TypeTranslator.GetArrayName (elem.ElementName);
}
// Avoid name colisions
XmlTypeMapping map = CreateTypeMapping (typeData, root, name, defaultNamespace);
map.ObjectMap = obmap;
-
+
+ // Register any of the including types as a derived class of object
+ XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
+
+ XmlTypeMapping objectMapping = ImportTypeMapping (typeof(object));
+ for (int i = 0; i < includes.Length; i++)
+ {
+ Type includedType = includes[i].Type;
+ objectMapping.DerivedTypes.Add(ImportTypeMapping (includedType, null, defaultNamespace));
+ }
+
// Register this map as a derived class of object
helper.RegisterSchemaType (map, name, defaultNamespace);
return map;
}
- string GetArrayName (string elemName)
- {
- return "ArrayOf" + Char.ToUpper (elemName [0]) + elemName.Substring (1);
- }
-
XmlTypeMapping ImportXmlNodeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (TypeTranslator.GetTypeData (type), root, defaultNamespace));
if (map != null) return map;
// Registers the maps for XmlNode and XmlElement
XmlTypeMapping nodeMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlNode)), root, null, defaultNamespace);
- helper.RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
+ helper.RegisterClrType (nodeMap, typeof(XmlNode), nodeMap.XmlTypeNamespace);
XmlTypeMapping elemMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlElement)), root, null, defaultNamespace);
- helper.RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
+ helper.RegisterClrType (elemMap, typeof(XmlElement), elemMap.XmlTypeNamespace);
XmlTypeMapping textMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlText)), root, null, defaultNamespace);
- helper.RegisterClrType (elemMap, typeof(XmlText), defaultNamespace);
+ helper.RegisterClrType (elemMap, typeof(XmlText), textMap.XmlTypeNamespace);
XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
obmap.DerivedTypes.Add (nodeMap);
nodeMap.DerivedTypes.Add (elemMap);
nodeMap.DerivedTypes.Add (textMap);
- return helper.GetRegisteredClrType (type, defaultNamespace);
+ return helper.GetRegisteredClrType (type, GetTypeNamespace (TypeTranslator.GetTypeData (type), root, defaultNamespace));
}
XmlTypeMapping ImportPrimitiveMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
if (map != null) return map;
- map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
- helper.RegisterClrType (map, type, defaultNamespace);
+ map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+ helper.RegisterClrType (map, type, map.XmlTypeNamespace);
return map;
}
XmlTypeMapping ImportEnumMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
if (map != null) return map;
- map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
- helper.RegisterClrType (map, type, defaultNamespace);
+ map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+ helper.RegisterClrType (map, type, map.XmlTypeNamespace);
string [] names = Enum.GetNames (type);
ArrayList members = new ArrayList();
foreach (string name in names)
{
MemberInfo[] mem = type.GetMember (name);
- string xmlName = name;
+ string xmlName = null;
object[] atts = mem[0].GetCustomAttributes (typeof(XmlIgnoreAttribute), false);
if (atts.Length > 0) continue;
atts = mem[0].GetCustomAttributes (typeof(XmlEnumAttribute), false);
if (atts.Length > 0) xmlName = ((XmlEnumAttribute)atts[0]).Name;
+ if (xmlName == null) xmlName = name;
members.Add (new EnumMap.EnumMapMember (xmlName, name));
}
XmlTypeMapping ImportXmlSerializableMapping (Type type, XmlRootAttribute root, string defaultNamespace)
{
- XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
if (map != null) return map;
- map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
- helper.RegisterClrType (map, type, defaultNamespace);
+ map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+ helper.RegisterClrType (map, type, map.XmlTypeNamespace);
return map;
}
- public ICollection GetReflectionMembers (Type type)
+ void ImportIncludedTypes (Type type, string defaultNamespace)
{
- ArrayList members = new ArrayList();
- PropertyInfo[] properties = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
- foreach (PropertyInfo prop in properties)
+ XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
+ for (int n=0; n<includes.Length; n++)
{
- if (!prop.CanRead) continue;
- XmlAttributes atts = attributeOverrides[type, prop.Name];
- if (atts == null) atts = new XmlAttributes (prop);
- if (atts.XmlIgnore) continue;
- XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
- members.Add (member);
+ Type includedType = includes[n].Type;
+ ImportTypeMapping (includedType, null, defaultNamespace);
}
+ }
- FieldInfo[] fields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
- foreach (FieldInfo field in fields)
+ ICollection GetReflectionMembers (Type type)
+ {
+ ArrayList members = new ArrayList();
+ MemberInfo[] tmembers = type.GetMembers (BindingFlags.Instance | BindingFlags.Public);
+ int currentTypePos = 0;
+ Type currentType = null;
+
+ foreach (MemberInfo tmember in tmembers)
{
- XmlAttributes atts = attributeOverrides[type, field.Name];
- if (atts == null) atts = new XmlAttributes (field);
- if (atts.XmlIgnore) continue;
- XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
- members.Add (member);
+ if (currentType != tmember.DeclaringType)
+ {
+ currentType = tmember.DeclaringType;
+ currentTypePos = 0;
+ }
+
+ if (tmember is FieldInfo)
+ {
+ FieldInfo field = tmember as FieldInfo;
+ XmlAttributes atts = attributeOverrides[type, field.Name];
+ if (atts == null) atts = new XmlAttributes (field);
+ if (atts.XmlIgnore) continue;
+ XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
+ members.Insert (currentTypePos, member);
+ currentTypePos++;
+ }
+ else if (tmember is PropertyInfo)
+ {
+ PropertyInfo prop = tmember as PropertyInfo;
+ if (!prop.CanRead) continue;
+ if (!prop.CanWrite && TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array)
+ continue;
+ if (prop.GetIndexParameters().Length > 0) continue;
+
+ XmlAttributes atts = attributeOverrides[type, prop.Name];
+ if (atts == null) atts = new XmlAttributes (prop);
+ if (atts.XmlIgnore) continue;
+ XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
+ members.Insert (currentTypePos, member);
+ currentTypePos++;
+ }
}
return members;
}
(rmember.MemberType.FullName == "System.Xml.XmlElement"))
{
XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
- member.ElementInfo = ImportAnyElementInfo (defaultNamespace, member, atts);
+ member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
mapMember = member;
}
else
else
mapAttribute.AttributeName = atts.XmlAttribute.AttributeName;
- mapAttribute.Form = atts.XmlAttribute.Form;
- mapAttribute.Namespace = (atts.XmlAttribute.Namespace != null) ? atts.XmlAttribute.Namespace : "";
if (typeData.IsComplexType)
mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
-
+
+ if (atts.XmlAttribute.Namespace != null && atts.XmlAttribute.Namespace != defaultNamespace)
+ {
+ if (atts.XmlAttribute.Form == XmlSchemaForm.Unqualified)
+ throw new InvalidOperationException ("The Form property may not be 'Unqualified' when an explicit Namespace property is present");
+ mapAttribute.Form = XmlSchemaForm.Qualified;
+ mapAttribute.Namespace = atts.XmlAttribute.Namespace;
+ }
+ else
+ {
+ mapAttribute.Form = atts.XmlAttribute.Form;
+ if (atts.XmlAttribute.Form == XmlSchemaForm.Qualified)
+ mapAttribute.Namespace = defaultNamespace;
+ else
+ mapAttribute.Namespace = "";
+ }
+
typeData = TypeTranslator.GetTypeData(rmember.MemberType, atts.XmlAttribute.DataType);
mapMember = mapAttribute;
}
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);
+ elem.IsNullable = (atts.XmlArray != null) ? atts.XmlArray.IsNullable : false;
+ elem.Form = (atts.XmlArray != null) ? atts.XmlArray.Form : XmlSchemaForm.Qualified;
+
member.ElementInfo.Add (elem);
mapMember = member;
}
{
XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
- if (atts.XmlText != null)
- {
- member.IsXmlTextCollector = true;
- if (atts.XmlText.Type != null) defaultType = atts.XmlText.Type;
- if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText); // Nodes must be text nodes
-
- XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
-
- if (elem.TypeData.SchemaType != SchemaTypes.Primitive && elem.TypeData.SchemaType != SchemaTypes.Enum &&
- elem.TypeData.SchemaType != SchemaTypes.XmlNode)
- throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
-
- elem.IsTextElement = true;
- elem.WrappedElement = false;
- list.Add (elem);
- }
-
+ ImportTextElementInfo (list, defaultType, member, atts);
+
if (atts.XmlElements.Count == 0 && list.Count == 0)
{
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType));
elem.Namespace = (att.Namespace != null) ? att.Namespace : defaultNamespace;
elem.Form = att.Form;
elem.IsNullable = att.IsNullable;
+
+ if (elem.IsNullable && elem.TypeData.IsValueType)
+ throw new InvalidOperationException ("IsNullable may not be 'true' for value type " + elem.TypeData.FullTypeName + " in member '" + defaultName + "'");
+
if (elem.TypeData.IsComplexType)
{
if (att.DataType != null) throw new InvalidOperationException ("'" + att.DataType + "' is an invalid value for the XmlElementAttribute.DateTime property. The property may only be specified for primitive types.");
return list;
}
- XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlTypeMapMemberElement member, XmlAttributes atts)
+ XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlReflectionMember rmember, XmlTypeMapMemberElement member, XmlAttributes atts)
{
XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
+ ImportTextElementInfo (list, rmember.MemberType, member, atts);
+
foreach (XmlAnyElementAttribute att in atts.XmlAnyElements)
{
XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
- if (att.Name != null && att.Name != string.Empty) elem.ElementName = att.Name;
- else elem.IsUnnamedAnyElement = true;
- elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
+ if (att.Name != null && att.Name != string.Empty)
+ {
+ elem.ElementName = att.Name;
+ elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
+ }
+ else
+ {
+ elem.IsUnnamedAnyElement = true;
+ elem.Namespace = defaultNamespace;
+ 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.");
+ }
list.Add (elem);
}
return list;
}
+ void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
+ {
+ if (atts.XmlText != null)
+ {
+ member.IsXmlTextCollector = true;
+ if (atts.XmlText.Type != null) defaultType = atts.XmlText.Type;
+ if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText); // Nodes must be text nodes
+
+ XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
+
+ if (elem.TypeData.SchemaType != SchemaTypes.Primitive &&
+ elem.TypeData.SchemaType != SchemaTypes.Enum &&
+ elem.TypeData.SchemaType != SchemaTypes.XmlNode &&
+ !(elem.TypeData.SchemaType == SchemaTypes.Array && elem.TypeData.ListItemTypeData.SchemaType == SchemaTypes.XmlNode)
+ )
+ throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
+
+ elem.IsTextElement = true;
+ elem.WrappedElement = false;
+ list.Add (elem);
+ }
+ }
+
+ bool CanBeNull (TypeData type)
+ {
+ return (type.SchemaType != SchemaTypes.Primitive || type.Type == typeof (string));
+ }
+
public void IncludeType (Type type)
{
if (type == null)
throw new ArgumentNullException ("type");
if (includedTypes == null) includedTypes = new ArrayList ();
- includedTypes.Add (type);
+ if (!includedTypes.Contains (type))
+ includedTypes.Add (type);
+ }
+
+ public void IncludeTypes (ICustomAttributeProvider provider)
+ {
+ object[] ats = provider.GetCustomAttributes (typeof(XmlIncludeAttribute), true);
+ foreach (XmlIncludeAttribute at in ats)
+ IncludeType (at.Type);
}
#endregion // Methods