using System.Collections;
using System.Globalization;
using System.Xml.Schema;
+using System.Reflection;
namespace System.Xml.Serialization
{
get { return type.TypeName; }
}
+#if NET_2_0
+ public string XsdTypeName
+ {
+ get { return XmlType; }
+ }
+
+ public string XsdTypeNamespace
+ {
+ get { return XmlTypeNamespace; }
+ }
+#endif
+
internal TypeData TypeData
{
get { return type; }
internal string XmlType
{
get { return xmlType; }
+ set { xmlType = value; }
}
internal string XmlTypeNamespace
{
- get { return xmlTypeNamespace; }
+ get { return xmlTypeNamespace ?? string.Empty; }
+ set { xmlTypeNamespace = value; }
+ }
+
+ internal bool HasXmlTypeNamespace
+ {
+ get { return xmlTypeNamespace != null; }
}
internal ArrayList DerivedTypes
set { isNullable = value; }
}
- internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)
+ internal XmlTypeMapping GetRealTypeMap (Type objectType)
{
if (TypeData.SchemaType == SchemaTypes.Enum)
return this;
// Returns the map for a subtype of this map's type
- objectFullTypeName = objectFullTypeName.Replace ('+','.');
- if (TypeFullName == objectFullTypeName) return this;
+ if (TypeData.Type == objectType) return this;
for (int n=0; n<_derivedTypes.Count; n++) {
XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];
- if (map.TypeFullName == objectFullTypeName) return map;
+ if (map.TypeData.Type == objectType) return map;
}
return null;
internal XmlTypeMapping GetRealElementMap (string name, string ens)
{
- if (xmlType == name && xmlTypeNamespace == ens) return this;
+ if (xmlType == name && XmlTypeNamespace == ens) return this;
foreach (XmlTypeMapping map in _derivedTypes)
- if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;
+ if (map.xmlType == name && map.XmlTypeNamespace == ens) return map;
return null;
}
internal class XmlSerializableMapping : XmlTypeMapping
{
XmlSchema _schema;
+#if NET_2_0 && !MOONLIGHT
+ XmlSchemaComplexType _schemaType;
+ XmlQualifiedName _schemaTypeName;
+#endif
- internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
+ internal XmlSerializableMapping(XmlRootAttribute root, string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
: base(elementName, ns, typeData, xmlType, xmlTypeNamespace)
{
- IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type);
+#if NET_2_0 && !MOONLIGHT
+ XmlSchemaProviderAttribute schemaProvider = (XmlSchemaProviderAttribute) Attribute.GetCustomAttribute (typeData.Type, typeof (XmlSchemaProviderAttribute));
+
+ if (schemaProvider != null) {
+ string method = schemaProvider.MethodName;
+ MethodInfo mi = typeData.Type.GetMethod (method, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
+ if (mi == null)
+ throw new InvalidOperationException (String.Format ("Type '{0}' must implement public static method '{1}'", typeData.Type, method));
+ if (!typeof (XmlQualifiedName).IsAssignableFrom (mi.ReturnType) &&
+ // LAMESPEC: it is undocumented. (We don't have to tell users about it in the error message.)
+ // Also do not add such a silly compatibility test to assert that it does not raise an error.
+ !typeof (XmlSchemaComplexType).IsAssignableFrom (mi.ReturnType))
+ throw new InvalidOperationException (String.Format ("Method '{0}' indicated by XmlSchemaProviderAttribute must have its return type as XmlQualifiedName", method));
+ XmlSchemaSet xs = new XmlSchemaSet ();
+ object retVal = mi.Invoke (null, new object [] { xs });
+ _schemaTypeName = XmlQualifiedName.Empty;
+ if (retVal == null)
+ return;
+
+ if (retVal is XmlSchemaComplexType) {
+ _schemaType = (XmlSchemaComplexType) retVal;
+ if (!_schemaType.QualifiedName.IsEmpty)
+ _schemaTypeName = _schemaType.QualifiedName;
+ else
+ _schemaTypeName = new XmlQualifiedName (xmlType, xmlTypeNamespace);
+ }
+ else if (retVal is XmlQualifiedName) {
+ _schemaTypeName = (XmlQualifiedName)retVal;
+ }
+ else
+ throw new InvalidOperationException (
+ String.Format ("Method {0}.{1}() specified by XmlSchemaProviderAttribute has invalid signature: return type must be compatible with System.Xml.XmlQualifiedName.", typeData.Type.Name, method));
+
+ // defaultNamespace at XmlReflectionImporter takes precedence for Namespace, but not for XsdTypeNamespace.
+ UpdateRoot (new XmlQualifiedName (root != null ? root.ElementName : _schemaTypeName.Name, root != null ? root.Namespace : Namespace ?? _schemaTypeName.Namespace));
+ XmlTypeNamespace = _schemaTypeName.Namespace;
+ XmlType = _schemaTypeName.Name;
+
+ if (!_schemaTypeName.IsEmpty && xs.Count > 0) {
+ XmlSchema [] schemas = new XmlSchema [xs.Count];
+ xs.CopyTo (schemas, 0);
+ _schema = schemas [0];
+ }
+
+ return;
+ }
+#endif
+#if NET_2_0 && !MOONLIGHT
+ IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type, true);
+ try {
+ _schema = serializable.GetSchema();
+ } catch (Exception) {
+ // LAMESPEC: .NET has a bad exception catch and swallows it silently.
+ }
+#else
+ IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type);
_schema = serializable.GetSchema();
+#endif
+#if !MOONLIGHT
if (_schema != null)
{
if (_schema.Id == null || _schema.Id.Length == 0)
throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id.");
}
+#endif
}
internal XmlSchema Schema
{
get { return _schema; }
}
+
+#if NET_2_0 && !MOONLIGHT
+ internal XmlSchemaType SchemaType {
+ get { return _schemaType; }
+ }
+
+ internal XmlQualifiedName SchemaTypeName {
+ get { return _schemaTypeName; }
+ }
+#endif
}
XmlTypeMapMember _returnMember;
bool _ignoreMemberNamespace;
bool _canBeSimpleType = true;
+ bool? _isOrderDependentMap;
public void AddMember (XmlTypeMapMember member)
{
- member.GlobalIndex = _allMembers.Count;
+ // If GlobalIndex has not been set, set it now
+ if (member.GlobalIndex == -1)
+ member.GlobalIndex = _allMembers.Count;
+
_allMembers.Add (member);
if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {
{
XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;
if (_attributeMembers == null) _attributeMembers = new Hashtable();
- string key = BuildKey (atm.AttributeName, atm.Namespace);
+ string key = BuildKey (atm.AttributeName, atm.Namespace, -1);
if (_attributeMembers.ContainsKey (key))
throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");
member.Index = _attributeMembers.Count;
ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;
foreach (XmlTypeMapElementInfo elem in elemsInfo)
{
- string key = BuildKey (elem.ElementName, elem.Namespace);
+ string key = BuildKey (elem.ElementName, elem.Namespace, elem.ExplicitOrder);
if (_elements.ContainsKey (key))
throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");
_elements.Add (key, elem);
public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)
{
if (_attributeMembers == null) return null;
- return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)];
+ return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey (name,ns, -1)];
}
- public XmlTypeMapElementInfo GetElement (string name, string ns)
+ public XmlTypeMapElementInfo GetElement (string name, string ns, int order)
{
if (_elements == null) return null;
- return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)];
+ return (XmlTypeMapElementInfo)_elements [BuildKey (name,ns, order)];
+ }
+
+ public XmlTypeMapElementInfo GetElement(string name, string ns)
+ {
+ if (_elements == null) return null;
+
+ foreach (XmlTypeMapElementInfo info in _elements.Values)
+ if (info.ElementName == name && info.Namespace == ns)
+ return info;
+
+ return null;
}
public XmlTypeMapElementInfo GetElement (int index)
_elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];
}
}
-
+ if (index >= _elementMembers.Count)
+ return null;
return _elementsByIndex [index];
}
- private string BuildKey (string name, string ns)
+ private string BuildKey (string name, string ns, int explicitOrder)
{
if (_ignoreMemberNamespace) return name;
- else return name + " / " + ns;
+ else return name + " / " + ns + (explicitOrder < 0 ? "" : "/" + explicitOrder);
}
public ICollection AllElementInfos
set { _ignoreMemberNamespace = value; }
}
+ public bool IsOrderDependentMap {
+ get {
+ if (_isOrderDependentMap == null) {
+ _isOrderDependentMap = false;
+ foreach (XmlTypeMapElementInfo ei in _elements.Values)
+ if (ei.ExplicitOrder >= 0) {
+ _isOrderDependentMap = true;
+ break;
+ }
+ }
+ return (bool) _isOrderDependentMap;
+ }
+ }
+
public XmlTypeMapMember FindMember (string name)
{
for (int n=0; n<_allMembers.Count; n++)