/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs
C# | 800 lines | 621 code | 98 blank | 81 comment | 167 complexity | 0f3e0299b57bb3675b51a17e5cec87c5 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, LGPL-2.1
- //
- // KnownTypeCollection.cs
- //
- // Author:
- // Atsushi Enomoto <atsushi@ximian.com>
- //
- // Copyright (C) 2005 Novell, Inc. http://www.novell.com
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- #if NET_2_0
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Reflection;
- using System.Xml;
- using System.Xml.Schema;
- using QName = System.Xml.XmlQualifiedName;
- using System.Xml.Serialization;
- namespace System.Runtime.Serialization
- {
- /*
- XmlFormatter implementation design inference:
- type definitions:
- - No XML Schema types are directly used. There are some maps from
- xs:blahType to ms:blahType where the namespaceURI for prefix "ms" is
- "http://schemas.microsoft.com/2003/10/Serialization/" .
- serializable types:
- - An object being serialized 1) must be of type System.Object, or
- 2) must be null, or 3) must have either a [DataContract] attribute
- or a [Serializable] attribute to be serializable.
- - When the object is either of type System.Object or null, then the
- XML type is "anyType".
- - When the object is [Serializable], then the runtime-serialization
- compatible object graph is written.
- - Otherwise the serialization is based on contract attributes.
- ([Serializable] takes precedence).
- type derivation:
- - For type A to be serializable, the base type B of A must be
- serializable.
- - If a type which is [Serializable] and whose base type has a
- [DataContract], then for base type members [DataContract] is taken.
- - It is vice versa i.e. if the base type is [Serializable] and the
- derived type has a [DataContract], then [Serializable] takes place
- for base members.
- known type collection:
- - It internally manages mapping store keyed by contract QNames.
- KnownTypeCollection.Add() checks if the same QName contract already
- exists (and raises InvalidOperationException if required).
- */
- internal static class TypeExtensions
- {
- public static T GetCustomAttribute<T> (this Type type, bool inherit)
- {
- var arr = type.GetCustomAttributes (typeof (T), inherit);
- return arr != null && arr.Length == 1 ? (T) arr [0] : default (T);
- }
- }
- internal sealed class KnownTypeCollection : Collection<Type>
- {
- internal const string MSSimpleNamespace =
- "http://schemas.microsoft.com/2003/10/Serialization/";
- internal const string MSArraysNamespace =
- "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
- internal const string DefaultClrNamespaceBase =
- "http://schemas.datacontract.org/2004/07/";
- static QName any_type, bool_type,
- byte_type, date_type, decimal_type, double_type,
- float_type, string_type,
- short_type, int_type, long_type,
- ubyte_type, ushort_type, uint_type, ulong_type,
- // non-TypeCode
- any_uri_type, base64_type, duration_type, qname_type,
- // custom in ms nsURI schema
- char_type, guid_type,
- // not in ms nsURI schema
- dbnull_type;
- static KnownTypeCollection ()
- {
- //any_type, bool_type, byte_type, date_type, decimal_type, double_type, float_type, string_type,
- // short_type, int_type, long_type, ubyte_type, ushort_type, uint_type, ulong_type,
- // any_uri_type, base64_type, duration_type, qname_type,
- // char_type, guid_type, dbnull_type;
- string s = MSSimpleNamespace;
- any_type = new QName ("anyType", s);
- any_uri_type = new QName ("anyURI", s);
- bool_type = new QName ("boolean", s);
- base64_type = new QName ("base64Binary", s);
- date_type = new QName ("dateTime", s);
- duration_type = new QName ("duration", s);
- qname_type = new QName ("QName", s);
- decimal_type = new QName ("decimal", s);
- double_type = new QName ("double", s);
- float_type = new QName ("float", s);
- byte_type = new QName ("byte", s);
- short_type = new QName ("short", s);
- int_type = new QName ("int", s);
- long_type = new QName ("long", s);
- ubyte_type = new QName ("unsignedByte", s);
- ushort_type = new QName ("unsignedShort", s);
- uint_type = new QName ("unsignedInt", s);
- ulong_type = new QName ("unsignedLong", s);
- string_type = new QName ("string", s);
- guid_type = new QName ("guid", s);
- char_type = new QName ("char", s);
- dbnull_type = new QName ("DBNull", MSSimpleNamespace + "System");
- }
- // FIXME: find out how QName and guid are processed
- internal QName GetXmlName (Type type)
- {
- SerializationMap map = FindUserMap (type);
- if (map != null)
- return map.XmlName;
- return GetPredefinedTypeName (type);
- }
- internal static QName GetPredefinedTypeName (Type type)
- {
- QName name = GetPrimitiveTypeName (type);
- if (name != QName.Empty)
- return name;
- if (type == typeof (DBNull))
- return dbnull_type;
- return QName.Empty;
- }
- internal static QName GetPrimitiveTypeName (Type type)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>))
- return GetPrimitiveTypeName (type.GetGenericArguments () [0]);
- if (type.IsEnum)
- return QName.Empty;
- switch (Type.GetTypeCode (type)) {
- case TypeCode.Object: // other than System.Object
- case TypeCode.DBNull: // it is natively mapped, but not in ms serialization namespace.
- case TypeCode.Empty:
- default:
- if (type == typeof (object))
- return any_type;
- if (type == typeof (Guid))
- return guid_type;
- if (type == typeof (TimeSpan))
- return duration_type;
- if (type == typeof (byte []))
- return base64_type;
- if (type == typeof (Uri))
- return any_uri_type;
- return QName.Empty;
- case TypeCode.Boolean:
- return bool_type;
- case TypeCode.Byte:
- return ubyte_type;
- case TypeCode.Char:
- return char_type;
- case TypeCode.DateTime:
- return date_type;
- case TypeCode.Decimal:
- return decimal_type;
- case TypeCode.Double:
- return double_type;
- case TypeCode.Int16:
- return short_type;
- case TypeCode.Int32:
- return int_type;
- case TypeCode.Int64:
- return long_type;
- case TypeCode.SByte:
- return byte_type;
- case TypeCode.Single:
- return float_type;
- case TypeCode.String:
- return string_type;
- case TypeCode.UInt16:
- return ushort_type;
- case TypeCode.UInt32:
- return uint_type;
- case TypeCode.UInt64:
- return ulong_type;
- }
- }
- internal static string PredefinedTypeObjectToString (object obj)
- {
- Type type = obj.GetType ();
- switch (Type.GetTypeCode (type)) {
- case TypeCode.Object: // other than System.Object
- case TypeCode.Empty:
- default:
- if (type == typeof (object))
- return String.Empty;
- if (type == typeof (Guid))
- return XmlConvert.ToString ((Guid) obj);
- if (type == typeof (TimeSpan))
- return XmlConvert.ToString ((TimeSpan) obj);
- if (type == typeof (byte []))
- return Convert.ToBase64String ((byte []) obj);
- if (type == typeof (Uri))
- return ((Uri) obj).ToString ();
- throw new Exception ("Internal error: missing predefined type serialization for type " + type.FullName);
- case TypeCode.DBNull: // predefined, but not primitive
- return String.Empty;
- case TypeCode.Boolean:
- return XmlConvert.ToString ((bool) obj);
- case TypeCode.Byte:
- return XmlConvert.ToString ((int)((byte) obj));
- case TypeCode.Char:
- return XmlConvert.ToString ((uint) (char) obj);
- case TypeCode.DateTime:
- return XmlConvert.ToString ((DateTime) obj, XmlDateTimeSerializationMode.RoundtripKind);
- case TypeCode.Decimal:
- return XmlConvert.ToString ((decimal) obj);
- case TypeCode.Double:
- return XmlConvert.ToString ((double) obj);
- case TypeCode.Int16:
- return XmlConvert.ToString ((short) obj);
- case TypeCode.Int32:
- return XmlConvert.ToString ((int) obj);
- case TypeCode.Int64:
- return XmlConvert.ToString ((long) obj);
- case TypeCode.SByte:
- return XmlConvert.ToString ((sbyte) obj);
- case TypeCode.Single:
- return XmlConvert.ToString ((float) obj);
- case TypeCode.String:
- return (string) obj;
- case TypeCode.UInt16:
- return XmlConvert.ToString ((int) (ushort) obj);
- case TypeCode.UInt32:
- return XmlConvert.ToString ((uint) obj);
- case TypeCode.UInt64:
- return XmlConvert.ToString ((ulong) obj);
- }
- }
- // FIXME: xsd types and ms serialization types should be differentiated.
- internal static Type GetPrimitiveTypeFromName (string name)
- {
- switch (name) {
- case "anyURI":
- return typeof (Uri);
- case "boolean":
- return typeof (bool);
- case "base64Binary":
- return typeof (byte []);
- case "dateTime":
- return typeof (DateTime);
- case "duration":
- return typeof (TimeSpan);
- case "QName":
- return typeof (QName);
- case "decimal":
- return typeof (decimal);
- case "double":
- return typeof (double);
- case "float":
- return typeof (float);
- case "byte":
- return typeof (sbyte);
- case "short":
- return typeof (short);
- case "int":
- return typeof (int);
- case "long":
- return typeof (long);
- case "unsignedByte":
- return typeof (byte);
- case "unsignedShort":
- return typeof (ushort);
- case "unsignedInt":
- return typeof (uint);
- case "unsignedLong":
- return typeof (ulong);
- case "string":
- return typeof (string);
- case "anyType":
- return typeof (object);
- case "guid":
- return typeof (Guid);
- case "char":
- return typeof (char);
- default:
- return null;
- }
- }
- internal static object PredefinedTypeStringToObject (string s,
- string name, XmlReader reader)
- {
- switch (name) {
- case "anyURI":
- return new Uri(s,UriKind.RelativeOrAbsolute);
- case "boolean":
- return XmlConvert.ToBoolean (s);
- case "base64Binary":
- return Convert.FromBase64String (s);
- case "dateTime":
- return XmlConvert.ToDateTime (s, XmlDateTimeSerializationMode.RoundtripKind);
- case "duration":
- return XmlConvert.ToTimeSpan (s);
- case "QName":
- int idx = s.IndexOf (':');
- string l = idx < 0 ? s : s.Substring (idx + 1);
- return idx < 0 ? new QName (l) :
- new QName (l, reader.LookupNamespace (
- s.Substring (0, idx)));
- case "decimal":
- return XmlConvert.ToDecimal (s);
- case "double":
- return XmlConvert.ToDouble (s);
- case "float":
- return XmlConvert.ToSingle (s);
- case "byte":
- return XmlConvert.ToSByte (s);
- case "short":
- return XmlConvert.ToInt16 (s);
- case "int":
- return XmlConvert.ToInt32 (s);
- case "long":
- return XmlConvert.ToInt64 (s);
- case "unsignedByte":
- return XmlConvert.ToByte (s);
- case "unsignedShort":
- return XmlConvert.ToUInt16 (s);
- case "unsignedInt":
- return XmlConvert.ToUInt32 (s);
- case "unsignedLong":
- return XmlConvert.ToUInt64 (s);
- case "string":
- return s;
- case "guid":
- return XmlConvert.ToGuid (s);
- case "anyType":
- return s;
- case "char":
- return (char) XmlConvert.ToUInt32 (s);
- default:
- throw new Exception ("Unanticipated primitive type: " + name);
- }
- }
- List<SerializationMap> contracts = new List<SerializationMap> ();
- public KnownTypeCollection ()
- {
- }
- protected override void ClearItems ()
- {
- base.Clear ();
- }
- protected override void InsertItem (int index, Type type)
- {
- if (TryRegister (type))
- base.InsertItem (index, type);
- }
- // FIXME: it could remove other types' dependencies.
- protected override void RemoveItem (int index)
- {
- Type t = base [index];
- List<SerializationMap> l = new List<SerializationMap> ();
- foreach (SerializationMap m in contracts) {
- if (m.RuntimeType == t)
- l.Add (m);
- }
- foreach (SerializationMap m in l) {
- contracts.Remove (m);
- base.RemoveItem (index);
- }
- }
- protected override void SetItem (int index, Type type)
- {
- if (index == Count)
- InsertItem (index, type);
- else {
- RemoveItem (index);
- if (TryRegister (type))
- base.InsertItem (index - 1, type);
- }
- }
- internal SerializationMap FindUserMap (QName qname)
- {
- for (int i = 0; i < contracts.Count; i++)
- if (qname == contracts [i].XmlName)
- return contracts [i];
- return null;
- }
- internal Type GetSerializedType (Type type)
- {
- Type element = GetCollectionElementType (type);
- if (element == null)
- return type;
- QName name = GetQName (type);
- var map = FindUserMap (name);
- if (map != null)
- return map.RuntimeType;
- return type;
- }
- internal SerializationMap FindUserMap (Type type)
- {
- for (int i = 0; i < contracts.Count; i++)
- if (type == contracts [i].RuntimeType)
- return contracts [i];
- return null;
- }
- internal QName GetQName (Type type)
- {
- if (IsPrimitiveNotEnum (type))
- return GetPrimitiveTypeName (type);
- SerializationMap map = FindUserMap (type);
- if (map != null)
- // already mapped.
- return map.XmlName;
- if (type.IsEnum)
- return GetEnumQName (type);
- QName qname = GetContractQName (type);
- if (qname != null)
- return qname;
- if (type.GetInterface ("System.Xml.Serialization.IXmlSerializable") != null)
- //FIXME: Reusing GetSerializableQName here, since we just
- //need name of the type..
- return GetSerializableQName (type);
- qname = GetCollectionContractQName (type);
- if (qname != null)
- return qname;
- Type element = GetCollectionElementType (type);
- if (element != null)
- return GetCollectionQName (element);
- if (GetAttribute<SerializableAttribute> (type) != null)
- return GetSerializableQName (type);
- // FIXME: it needs in-depth check.
- return QName.Empty;
- }
- QName GetContractQName (Type type)
- {
- var a = GetAttribute<DataContractAttribute> (type);
- return a == null ? null : GetContractQName (type, a.Name, a.Namespace);
- }
- QName GetCollectionContractQName (Type type)
- {
- var a = GetAttribute<CollectionDataContractAttribute> (type);
- return a == null ? null : GetContractQName (type, a.Name, a.Namespace);
- }
- internal static QName GetContractQName (Type type, string name, string ns)
- {
- if (name == null) {
- // FIXME: there could be decent ways to get
- // the same result...
- name = type.Namespace == null || type.Namespace.Length == 0 ? type.Name : type.FullName.Substring (type.Namespace.Length + 1).Replace ('+', '.');
- if (type.IsGenericType) {
- name = name.Substring (0, name.IndexOf ('`')) + "Of";
- foreach (var t in type.GetGenericArguments ())
- name += t.Name; // FIXME: check namespaces too
- }
- }
- if (ns == null)
- ns = DefaultClrNamespaceBase + type.Namespace;
- return new QName (name, ns);
- }
- private QName GetEnumQName (Type type)
- {
- string name = null, ns = null;
- if (!type.IsEnum)
- return null;
- var dca = GetAttribute<DataContractAttribute> (type);
- if (dca != null) {
- ns = dca.Namespace;
- name = dca.Name;
- }
- if (ns == null)
- ns = DefaultClrNamespaceBase + type.Namespace;
- if (name == null)
- name = type.Namespace == null ? type.Name : type.FullName.Substring (type.Namespace.Length + 1).Replace ('+', '.');
- return new QName (name, ns);
- }
- private QName GetCollectionQName (Type element)
- {
- QName eqname = GetQName (element);
-
- string ns = eqname.Namespace;
- if (eqname.Namespace == MSSimpleNamespace)
- //Arrays of Primitive types
- ns = MSArraysNamespace;
- return new QName (
- "ArrayOf" + XmlConvert.EncodeLocalName (eqname.Name),
- ns);
- }
- private QName GetSerializableQName (Type type)
- {
- string xmlName = type.Name;
- if (type.IsGenericType) {
- xmlName = xmlName.Substring (0, xmlName.IndexOf ('`')) + "Of";
- foreach (var t in type.GetGenericArguments ())
- xmlName += GetQName (t).Name; // FIXME: check namespaces too
- }
- string xmlNamespace = DefaultClrNamespaceBase + type.Namespace;
- var x = GetAttribute<XmlRootAttribute> (type);
- if (x != null) {
- xmlName = x.ElementName;
- xmlNamespace = x.Namespace;
- }
- return new QName (XmlConvert.EncodeLocalName (xmlName), xmlNamespace);
- }
- internal bool IsPrimitiveNotEnum (Type type)
- {
- if (type.IsEnum)
- return false;
- if (Type.GetTypeCode (type) != TypeCode.Object) // explicitly primitive
- return true;
- if (type == typeof (Guid) || type == typeof (object) || type == typeof(TimeSpan) || type == typeof(byte[]) || type==typeof(Uri)) // special primitives
- return true;
- // nullable
- if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>))
- return IsPrimitiveNotEnum (type.GetGenericArguments () [0]);
- return false;
- }
- internal bool TryRegister (Type type)
- {
- // exclude predefined maps
- if (IsPrimitiveNotEnum (type))
- return false;
- if (FindUserMap (type) != null)
- return false;
- if (RegisterEnum (type) != null)
- return true;
- if (RegisterContract (type) != null)
- return true;
- if (RegisterIXmlSerializable (type) != null)
- return true;
- if (RegisterDictionary (type) != null)
- return true;
- if (RegisterCollectionContract (type) != null)
- return true;
- if (RegisterCollection (type) != null)
- return true;
- if (GetAttribute<SerializableAttribute> (type) != null) {
- RegisterSerializable (type);
- return true;
- }
- RegisterDefaultTypeMap (type);
- return true;
- }
- internal static Type GetCollectionElementType (Type type)
- {
- if (type.IsArray)
- return type.GetElementType ();
- Type [] ifaces = type.GetInterfaces ();
- foreach (Type i in ifaces)
- if (i.IsGenericType && i.GetGenericTypeDefinition ().Equals (typeof (ICollection<>)))
- return i.GetGenericArguments () [0];
- foreach (Type i in ifaces)
- if (i == typeof (IList))
- return typeof (object);
- return null;
- }
- internal T GetAttribute<T> (MemberInfo mi) where T : Attribute
- {
- object [] atts = mi.GetCustomAttributes (typeof (T), false);
- return atts.Length == 0 ? null : (T) atts [0];
- }
- private CollectionContractTypeMap RegisterCollectionContract (Type type)
- {
- var cdca = GetAttribute<CollectionDataContractAttribute> (type);
- if (cdca == null)
- return null;
- Type element = GetCollectionElementType (type);
- if (element == null)
- throw new InvalidOperationException (String.Format ("Type '{0}' is marked as collection contract, but it is not a collection", type));
- TryRegister (element); // must be registered before the name conflict check.
- QName qname = GetCollectionContractQName (type);
- CheckStandardQName (qname);
- if (FindUserMap (qname) != null)
- throw new InvalidOperationException (String.Format ("Failed to add type {0} to known type collection. There already is a registered type for XML name {1}", type, qname));
- var ret = new CollectionContractTypeMap (type, cdca, element, qname, this);
- contracts.Add (ret);
- return ret;
- }
- private CollectionTypeMap RegisterCollection (Type type)
- {
- Type element = GetCollectionElementType (type);
- if (element == null)
- return null;
- TryRegister (element);
- QName qname = GetCollectionQName (element);
- var map = FindUserMap (qname);
- if (map != null) {
- var cmap = map as CollectionTypeMap;
- if (cmap == null || cmap.RuntimeType != type)
- throw new InvalidOperationException (String.Format ("Failed to add type {0} to known type collection. There already is a registered type for XML name {1}", type, qname));
- return cmap;
- }
- CollectionTypeMap ret =
- new CollectionTypeMap (type, element, qname, this);
- contracts.Add (ret);
- return ret;
- }
- static bool TypeImplementsIDictionary (Type type)
- {
- foreach (var iface in type.GetInterfaces ())
- if (iface == typeof (IDictionary) || (iface.IsGenericType && iface.GetGenericTypeDefinition () == typeof (IDictionary<,>)))
- return true;
- return false;
- }
- // it also supports contract-based dictionary.
- private DictionaryTypeMap RegisterDictionary (Type type)
- {
- if (!TypeImplementsIDictionary (type))
- return null;
- var cdca = GetAttribute<CollectionDataContractAttribute> (type);
- DictionaryTypeMap ret =
- new DictionaryTypeMap (type, cdca, this);
- if (FindUserMap (ret.XmlName) != null)
- throw new InvalidOperationException (String.Format ("Failed to add type {0} to known type collection. There already is a registered type for XML name {1}", type, ret.XmlName));
- contracts.Add (ret);
- TryRegister (ret.KeyType);
- TryRegister (ret.ValueType);
- return ret;
- }
- private SerializationMap RegisterSerializable (Type type)
- {
- QName qname = GetSerializableQName (type);
- if (FindUserMap (qname) != null)
- throw new InvalidOperationException (String.Format ("There is already a registered type for XML name {0}", qname));
- SharedTypeMap ret =
- new SharedTypeMap (type, qname, this);
- contracts.Add (ret);
- return ret;
- }
- private SerializationMap RegisterIXmlSerializable (Type type)
- {
- if (type.GetInterface ("System.Xml.Serialization.IXmlSerializable") == null)
- return null;
- QName qname = GetSerializableQName (type);
- if (FindUserMap (qname) != null)
- throw new InvalidOperationException (String.Format ("There is already a registered type for XML name {0}", qname));
- XmlSerializableMap ret = new XmlSerializableMap (type, qname, this);
- contracts.Add (ret);
- return ret;
- }
- void CheckStandardQName (QName qname)
- {
- switch (qname.Namespace) {
- case XmlSchema.Namespace:
- case XmlSchema.InstanceNamespace:
- case MSSimpleNamespace:
- case MSArraysNamespace:
- throw new InvalidOperationException (String.Format ("Namespace {0} is reserved and cannot be used for user serialization", qname.Namespace));
- }
- }
- private SharedContractMap RegisterContract (Type type)
- {
- QName qname = GetContractQName (type);
- if (qname == null)
- return null;
- CheckStandardQName (qname);
- if (FindUserMap (qname) != null)
- throw new InvalidOperationException (String.Format ("There is already a registered type for XML name {0}", qname));
- SharedContractMap ret = new SharedContractMap (type, qname, this);
- contracts.Add (ret);
- ret.Initialize ();
- object [] attrs = type.GetCustomAttributes (typeof (KnownTypeAttribute), true);
- for (int i = 0; i < attrs.Length; i++) {
- KnownTypeAttribute kt = (KnownTypeAttribute) attrs [i];
- TryRegister (kt.Type);
- }
- return ret;
- }
- DefaultTypeMap RegisterDefaultTypeMap (Type type)
- {
- DefaultTypeMap ret = new DefaultTypeMap (type, this);
- contracts.Add (ret);
- return ret;
- }
- private EnumMap RegisterEnum (Type type)
- {
- QName qname = GetEnumQName (type);
- if (qname == null)
- return null;
- if (FindUserMap (qname) != null)
- throw new InvalidOperationException (String.Format ("There is already a registered type for XML name {0}", qname));
- EnumMap ret =
- new EnumMap (type, qname, this);
- contracts.Add (ret);
- return ret;
- }
- }
- }
- #endif