Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Xml / System / Xml / Serialization / Types.cs / 5 / Types.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml.Serialization { using System; using System.IO; using System.Reflection; using System.Collections; using System.Xml.Schema; using System.Xml; using System.Text; using System.ComponentModel; using System.CodeDom; using System.CodeDom.Compiler; using System.Xml.Serialization.Advanced; using System.Globalization; using System.Security.Cryptography; // These classes provide a higher level view on reflection specific to // Xml serialization, for example: // - allowing one to talk about types w/o having them compiled yet // - abstracting collections & arrays // - abstracting classes, structs, interfaces // - knowing about XSD primitives // - dealing with Serializable and xmlelement // and lots of other little details internal enum TypeKind { Root, Primitive, Enum, Struct, Class, Array, Collection, Enumerable, Void, Node, Attribute, Serializable } internal enum TypeFlags { None = 0x0, Abstract = 0x1, Reference = 0x2, Special = 0x4, CanBeAttributeValue = 0x8, CanBeTextValue = 0x10, CanBeElementValue = 0x20, HasCustomFormatter = 0x40, AmbiguousDataType = 0x80, IgnoreDefault = 0x200, HasIsEmpty = 0x400, HasDefaultConstructor = 0x800, XmlEncodingNotRequired = 0x1000, UseReflection = 0x4000, CollapseWhitespace = 0x8000, OptionalValue = 0x10000, CtorInaccessible = 0x20000, UsePrivateImplementation = 0x40000, GenericInterface = 0x80000, Unsupported = 0x100000, } internal class TypeDesc { string name; string fullName; string cSharpName; TypeDesc arrayElementTypeDesc; TypeDesc arrayTypeDesc; TypeDesc nullableTypeDesc; TypeKind kind; XmlSchemaType dataType; Type type; TypeDesc baseTypeDesc; TypeFlags flags; string formatterName; bool isXsdType; bool isMixed; MappedTypeDesc extendedType; int weight; Exception exception; internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, string formatterName) { this.name = name.Replace('+', '.'); this.fullName = fullName.Replace('+', '.'); this.kind = kind; this.baseTypeDesc = baseTypeDesc; this.flags = flags; this.isXsdType = kind == TypeKind.Primitive; if (this.isXsdType) this.weight = 1; else if (kind == TypeKind.Enum) this.weight = 2; else if (this.kind == TypeKind.Root) this.weight = -1; else this.weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1; this.dataType = dataType; this.formatterName = formatterName; } internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, dataType, kind, baseTypeDesc, flags, null) {} internal TypeDesc(string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, (XmlSchemaType)null, kind, baseTypeDesc, flags, null) {} internal TypeDesc(Type type, bool isXsdType, XmlSchemaType dataType, string formatterName, TypeFlags flags) : this(type.Name, type.FullName, dataType, TypeKind.Primitive, (TypeDesc)null, flags, formatterName) { this.isXsdType = isXsdType; this.type = type; } internal TypeDesc(Type type, string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, TypeDesc arrayElementTypeDesc) : this(name, fullName, null, kind, baseTypeDesc, flags, null) { this.arrayElementTypeDesc = arrayElementTypeDesc; this.type = type; } public override string ToString() { return fullName; } internal TypeFlags Flags { get { return flags; } } internal bool IsXsdType { get { return isXsdType; } } internal bool IsMappedType { get { return extendedType != null; } } internal MappedTypeDesc ExtendedType { get { return extendedType; } } internal string Name { get { return name; } } internal string FullName { get { return fullName; } } internal string CSharpName { get { if (cSharpName == null) { cSharpName = type == null ? CodeIdentifier.GetCSharpName(fullName) : CodeIdentifier.GetCSharpName(type); } return cSharpName; } } internal XmlSchemaType DataType { get { return dataType; } } internal Type Type { get { return type; } } internal string FormatterName { get { return formatterName; } } internal TypeKind Kind { get { return kind; } } internal bool IsValueType { get { return (flags & TypeFlags.Reference) == 0; } } internal bool CanBeAttributeValue { get { return (flags & TypeFlags.CanBeAttributeValue) != 0; } } internal bool XmlEncodingNotRequired { get { return (flags & TypeFlags.XmlEncodingNotRequired) != 0; } } internal bool CanBeElementValue { get { return (flags & TypeFlags.CanBeElementValue) != 0; } } internal bool CanBeTextValue { get { return (flags & TypeFlags.CanBeTextValue) != 0; } } internal bool IsMixed { get { return isMixed || CanBeTextValue; } set { isMixed = value; } } internal bool IsSpecial { get { return (flags & TypeFlags.Special) != 0; } } internal bool IsAmbiguousDataType { get { return (flags & TypeFlags.AmbiguousDataType) != 0; } } internal bool HasCustomFormatter { get { return (flags & TypeFlags.HasCustomFormatter) != 0; } } internal bool HasDefaultSupport { get { return (flags & TypeFlags.IgnoreDefault) == 0; } } internal bool HasIsEmpty { get { return (flags & TypeFlags.HasIsEmpty) != 0; } } internal bool CollapseWhitespace { get { return (flags & TypeFlags.CollapseWhitespace) != 0; } } internal bool HasDefaultConstructor { get { return (flags & TypeFlags.HasDefaultConstructor) != 0; } } internal bool IsUnsupported { get { return (flags & TypeFlags.Unsupported) != 0; } } internal bool IsGenericInterface { get { return (flags & TypeFlags.GenericInterface) != 0; } } internal bool IsPrivateImplementation { get { return (flags & TypeFlags.UsePrivateImplementation) != 0; } } internal bool CannotNew { get { return !HasDefaultConstructor || ConstructorInaccessible; } } internal bool IsAbstract { get { return (flags & TypeFlags.Abstract) != 0; } } internal bool IsOptionalValue { get { return (flags & TypeFlags.OptionalValue) != 0; } } internal bool UseReflection { get { return (flags & TypeFlags.UseReflection) != 0; } } internal bool IsVoid { get { return kind == TypeKind.Void; } } internal bool IsClass { get { return kind == TypeKind.Class; } } internal bool IsStructLike { get { return kind == TypeKind.Struct || kind == TypeKind.Class; } } internal bool IsArrayLike { get { return kind == TypeKind.Array || kind == TypeKind.Collection || kind == TypeKind.Enumerable; } } internal bool IsCollection { get { return kind == TypeKind.Collection; } } internal bool IsEnumerable { get { return kind == TypeKind.Enumerable; } } internal bool IsArray { get { return kind == TypeKind.Array; } } internal bool IsPrimitive { get { return kind == TypeKind.Primitive; } } internal bool IsEnum { get { return kind == TypeKind.Enum; } } internal bool IsNullable { get { return !IsValueType; } } internal bool IsRoot { get { return kind == TypeKind.Root; } } internal bool ConstructorInaccessible { get { return (flags & TypeFlags.CtorInaccessible) != 0; } } internal Exception Exception { get { return exception; } set { exception = value; } } internal TypeDesc GetNullableTypeDesc(Type type) { if (IsOptionalValue) return this; if (nullableTypeDesc == null) { nullableTypeDesc = new TypeDesc("NullableOf" + this.name, "System.Nullable`1[" + this.fullName + "]", null, TypeKind.Struct, this, this.flags | TypeFlags.OptionalValue, this.formatterName); nullableTypeDesc.type = type; } return nullableTypeDesc; } internal void CheckSupported() { if (IsUnsupported) { if (Exception != null) { throw Exception; } else { throw new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, FullName)); } } if (baseTypeDesc != null) baseTypeDesc.CheckSupported(); if (arrayElementTypeDesc != null) arrayElementTypeDesc.CheckSupported(); } internal void CheckNeedConstructor() { if (!IsValueType && !IsAbstract && !HasDefaultConstructor) { flags |= TypeFlags.Unsupported; this.exception = new InvalidOperationException(Res.GetString(Res.XmlConstructorInaccessible, FullName)); } } internal string ArrayLengthName { get { return kind == TypeKind.Array ? "Length" : "Count"; } } internal TypeDesc ArrayElementTypeDesc { get { return arrayElementTypeDesc; } set { arrayElementTypeDesc = value; } } internal int Weight { get { return weight; } } internal TypeDesc CreateArrayTypeDesc() { if (arrayTypeDesc == null) arrayTypeDesc = new TypeDesc(null, name + "[]", fullName + "[]", TypeKind.Array, null, TypeFlags.Reference|(flags & TypeFlags.UseReflection), this); return arrayTypeDesc; } internal TypeDesc CreateMappedTypeDesc(MappedTypeDesc extension) { TypeDesc newTypeDesc = new TypeDesc(extension.Name, extension.Name, null, this.kind, this.baseTypeDesc, this.flags, null); newTypeDesc.isXsdType = this.isXsdType; newTypeDesc.isMixed = this.isMixed; newTypeDesc.extendedType = extension; newTypeDesc.dataType = this.dataType; return newTypeDesc; } internal TypeDesc BaseTypeDesc { get { return baseTypeDesc; } set { baseTypeDesc = value; weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1; } } internal bool IsDerivedFrom(TypeDesc baseTypeDesc) { TypeDesc typeDesc = this; while (typeDesc != null) { if (typeDesc == baseTypeDesc) return true; typeDesc = typeDesc.BaseTypeDesc; } return baseTypeDesc.IsRoot; } internal static TypeDesc FindCommonBaseTypeDesc(TypeDesc[] typeDescs) { if (typeDescs.Length == 0) return null; TypeDesc leastDerivedTypeDesc = null; int leastDerivedLevel = int.MaxValue; for (int i = 0; i < typeDescs.Length; i++) { int derivationLevel = typeDescs[i].Weight; if (derivationLevel < leastDerivedLevel) { leastDerivedLevel = derivationLevel; leastDerivedTypeDesc = typeDescs[i]; } } while (leastDerivedTypeDesc != null) { int i; for (i = 0; i < typeDescs.Length; i++) { if (!typeDescs[i].IsDerivedFrom(leastDerivedTypeDesc)) break; } if (i == typeDescs.Length) break; leastDerivedTypeDesc = leastDerivedTypeDesc.BaseTypeDesc; } return leastDerivedTypeDesc; } } internal class TypeScope { Hashtable typeDescs = new Hashtable(); Hashtable arrayTypeDescs = new Hashtable(); ArrayList typeMappings = new ArrayList(); static Hashtable primitiveTypes = new Hashtable(); static Hashtable primitiveDataTypes = new Hashtable(); static NameTable primitiveNames = new NameTable(); static string[] unsupportedTypes = new string[] { "anyURI", "duration", "ENTITY", "ENTITIES", "gDay", "gMonth", "gMonthDay", "gYear", "gYearMonth", "ID", "IDREF", "IDREFS", "integer", "language", "negativeInteger", "nonNegativeInteger", "nonPositiveInteger", //"normalizedString", "NOTATION", "positiveInteger", "token" }; static TypeScope() { AddPrimitive(typeof(string), "string", "String", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); AddPrimitive(typeof(int), "int", "Int32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(bool), "boolean", "Boolean", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(short), "short", "Int16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(long), "long", "Int64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(float), "float", "Single", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(double), "double", "Double", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(decimal), "decimal", "Decimal", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(DateTime), "dateTime", "DateTime", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(XmlQualifiedName), "QName", "XmlQualifiedName", TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference); AddPrimitive(typeof(byte), "unsignedByte", "Byte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(SByte), "byte", "SByte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt16), "unsignedShort", "UInt16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt32), "unsignedInt", "UInt32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt64), "unsignedLong", "UInt64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); // Types without direct mapping (ambigous) AddPrimitive(typeof(DateTime), "date", "Date", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(DateTime), "time", "Time", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(string), "Name", "XmlName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NCName", "XmlNCName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NMTOKEN", "XmlNmToken", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NMTOKENS", "XmlNmTokens", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(byte[]), "base64Binary", "ByteArrayBase64", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor); AddPrimitive(typeof(byte[]), "hexBinary", "ByteArrayHex", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor); // NOTE, [....]: byte[] can also be used to mean array of bytes. That datatype is not a primitive, so we // can't use the AmbiguousDataType mechanism. To get an array of bytes in literal XML, apply [XmlArray] or // [XmlArrayItem]. XmlSchemaPatternFacet guidPattern = new XmlSchemaPatternFacet(); guidPattern.Value = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"; AddNonXsdPrimitive(typeof(Guid), "guid", UrtTypes.Namespace, "Guid", new XmlQualifiedName("string", XmlSchema.Namespace), new XmlSchemaFacet[] { guidPattern }, TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.IgnoreDefault); AddNonXsdPrimitive(typeof(char), "char", UrtTypes.Namespace, "Char", new XmlQualifiedName("unsignedShort", XmlSchema.Namespace), new XmlSchemaFacet[0], TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.IgnoreDefault); AddSoapEncodedTypes(Soap.Encoding); // Unsuppoted types that we map to string, if in the future we decide // to add support for them we would need to create custom formatters for them // normalizedString is the only one unsuported type that suppose to preserve whitesapce AddPrimitive(typeof(string), "normalizedString", "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); for (int i = 0; i < unsupportedTypes.Length; i++) { AddPrimitive(typeof(string), unsupportedTypes[i], "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace); } } internal static bool IsKnownType(Type type) { if (type == typeof(object)) return true; if (type.IsEnum) return false; switch (Type.GetTypeCode(type)) { case TypeCode.String: return true; case TypeCode.Int32: return true; case TypeCode.Boolean: return true; case TypeCode.Int16: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; case TypeCode.Decimal: return true; case TypeCode.DateTime: return true; case TypeCode.Byte: return true; case TypeCode.SByte: return true; case TypeCode.UInt16: return true; case TypeCode.UInt32: return true; case TypeCode.UInt64: return true; case TypeCode.Char: return true; default: if (type == typeof(XmlQualifiedName)) return true; else if (type == typeof(byte[])) return true; else if (type == typeof(Guid)) return true; else if (type == typeof(XmlNode[])){ return true; } break; } return false; } static void AddSoapEncodedTypes(string ns) { AddSoapEncodedPrimitive(typeof(string), "normalizedString", ns, "String", new XmlQualifiedName("normalizedString", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); for (int i = 0; i < unsupportedTypes.Length; i++) { AddSoapEncodedPrimitive(typeof(string), unsupportedTypes[i], ns, "String", new XmlQualifiedName(unsupportedTypes[i], XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace); } AddSoapEncodedPrimitive(typeof(string), "string", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(int), "int", ns, "Int32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(bool), "boolean", ns, "Boolean", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(short), "short", ns, "Int16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(long), "long", ns, "Int64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(float), "float", ns, "Single", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(double), "double", ns, "Double", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(decimal), "decimal", ns, "Decimal", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(DateTime), "dateTime", ns, "DateTime", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(XmlQualifiedName), "QName", ns, "XmlQualifiedName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(byte), "unsignedByte", ns, "Byte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(SByte), "byte", ns, "SByte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt16), "unsignedShort", ns, "UInt16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt32), "unsignedInt", ns, "UInt32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt64), "unsignedLong", ns, "UInt64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); // Types without direct mapping (ambigous) AddSoapEncodedPrimitive(typeof(DateTime), "date", ns, "Date", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(DateTime), "time", ns, "Time", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(string), "Name", ns, "XmlName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NCName", ns, "XmlNCName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NMTOKEN", ns, "XmlNmToken", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NMTOKENS", ns, "XmlNmTokens", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(byte[]), "base64Binary", ns, "ByteArrayBase64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(byte[]), "hexBinary", ns, "ByteArrayHex", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(string), "arrayCoordinate", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue); AddSoapEncodedPrimitive(typeof(byte[]), "base64", ns, "ByteArrayBase64", new XmlQualifiedName("base64Binary", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.IgnoreDefault | TypeFlags.Reference); } static void AddPrimitive(Type type, string dataTypeName, string formatterName, TypeFlags flags) { XmlSchemaSimpleType dataType = new XmlSchemaSimpleType(); dataType.Name = dataTypeName; TypeDesc typeDesc = new TypeDesc(type, true, dataType, formatterName, flags); if (primitiveTypes[type] == null) primitiveTypes.Add(type, typeDesc); primitiveDataTypes.Add(dataType, typeDesc); primitiveNames.Add(dataTypeName, XmlSchema.Namespace, typeDesc); } static void AddNonXsdPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, XmlSchemaFacet[] facets, TypeFlags flags) { XmlSchemaSimpleType dataType = new XmlSchemaSimpleType(); dataType.Name = dataTypeName; XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction(); restriction.BaseTypeName = baseTypeName; foreach (XmlSchemaFacet facet in facets) { restriction.Facets.Add(facet); } dataType.Content = restriction; TypeDesc typeDesc = new TypeDesc(type, false, dataType, formatterName, flags); if (primitiveTypes[type] == null) primitiveTypes.Add(type, typeDesc); primitiveDataTypes.Add(dataType, typeDesc); primitiveNames.Add(dataTypeName, ns, typeDesc); } static void AddSoapEncodedPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, TypeFlags flags) { AddNonXsdPrimitive(type, dataTypeName, ns, formatterName, baseTypeName, new XmlSchemaFacet[0], flags); } internal TypeDesc GetTypeDesc(string name, string ns) { return GetTypeDesc(name, ns, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.CanBeAttributeValue); } internal TypeDesc GetTypeDesc(string name, string ns, TypeFlags flags) { TypeDesc typeDesc = (TypeDesc)primitiveNames[name, ns]; if (typeDesc != null) { if ((typeDesc.Flags & flags) != 0) { return typeDesc; } } return null; } internal TypeDesc GetTypeDesc(XmlSchemaSimpleType dataType) { return (TypeDesc)primitiveDataTypes[dataType]; } internal TypeDesc GetTypeDesc(Type type) { return GetTypeDesc(type, null, true, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source) { return GetTypeDesc(type, source, true, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference) { return GetTypeDesc(type, source, directReference, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference, bool throwOnError) { if (type.ContainsGenericParameters) { throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedOpenGenericType, type.ToString())); } TypeDesc typeDesc = (TypeDesc)primitiveTypes[type]; if (typeDesc == null) { typeDesc = (TypeDesc)typeDescs[type]; if (typeDesc == null) { typeDesc = ImportTypeDesc(type, source, directReference); } } if (throwOnError) typeDesc.CheckSupported(); return typeDesc; } internal TypeDesc GetArrayTypeDesc(Type type) { TypeDesc typeDesc = (TypeDesc) arrayTypeDescs[type]; if (typeDesc == null) { typeDesc = GetTypeDesc(type); if (!typeDesc.IsArrayLike) typeDesc = ImportTypeDesc(type, null, false); typeDesc.CheckSupported(); arrayTypeDescs.Add(type, typeDesc); } return typeDesc; } internal TypeMapping GetTypeMappingFromTypeDesc(TypeDesc typeDesc){ foreach(TypeMapping typeMapping in TypeMappings){ if (typeMapping.TypeDesc == typeDesc) return typeMapping; } return null; } internal Type GetTypeFromTypeDesc(TypeDesc typeDesc){ if (typeDesc.Type != null) return typeDesc.Type; foreach(DictionaryEntry de in typeDescs){ if (de.Value == typeDesc) return de.Key as Type; } return null; } TypeDesc ImportTypeDesc(Type type, MemberInfo memberInfo, bool directReference) { TypeDesc typeDesc = null; TypeKind kind; Type arrayElementType = null; Type baseType = null; TypeFlags flags = 0; Exception exception = null; if (!type.IsPublic && !type.IsNestedPublic) { flags |= TypeFlags.Unsupported; exception = new InvalidOperationException(Res.GetString(Res.XmlTypeInaccessible, type.FullName)); } else if (type.IsAbstract && type.IsSealed) { flags |= TypeFlags.Unsupported; exception = new InvalidOperationException(Res.GetString(Res.XmlTypeStatic, type.FullName)); } if (DynamicAssemblies.IsTypeDynamic(type)){ flags |= TypeFlags.UseReflection; } if (!type.IsValueType) flags |= TypeFlags.Reference; if (type == typeof(object)) { kind = TypeKind.Root; flags |= TypeFlags.HasDefaultConstructor; } else if (type == typeof(ValueType)) { kind = TypeKind.Enum; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } else if (type == typeof(void)) { kind = TypeKind.Void; } else if (typeof(IXmlSerializable).IsAssignableFrom(type)) { // kind = TypeKind.Serializable; flags |= TypeFlags.Special | TypeFlags.CanBeElementValue; flags |= GetConstructorFlags(type, ref exception); } else if (type.IsArray) { kind = TypeKind.Array; if (type.GetArrayRank() > 1) { flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedRank, type.FullName)); } } arrayElementType = type.GetElementType(); flags |= TypeFlags.HasDefaultConstructor; } else if (typeof(ICollection).IsAssignableFrom(type)) { kind = TypeKind.Collection; arrayElementType = GetCollectionElementType(type, memberInfo == null ? null : memberInfo.DeclaringType.FullName + "." + memberInfo.Name); flags |= GetConstructorFlags(type, ref exception); } else if (type == typeof(XmlQualifiedName)) { kind = TypeKind.Primitive; } else if (type.IsPrimitive) { kind = TypeKind.Primitive; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } else if (type.IsEnum) { kind = TypeKind.Enum; } else if (type.IsValueType) { kind = TypeKind.Struct; if (IsOptionalValue(type)) { baseType = type.GetGenericArguments()[0]; flags |= TypeFlags.OptionalValue; } else { baseType = type.BaseType; } if (type.IsAbstract) flags |= TypeFlags.Abstract; } else if (type.IsClass) { if (type == typeof(XmlAttribute)) { kind = TypeKind.Attribute; flags |= TypeFlags.Special | TypeFlags.CanBeAttributeValue; } else if (typeof(XmlNode).IsAssignableFrom(type)) { kind = TypeKind.Node; baseType = type.BaseType; flags |= TypeFlags.Special | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue; if (typeof(XmlText).IsAssignableFrom(type)) flags &= ~TypeFlags.CanBeElementValue; else if (typeof(XmlElement).IsAssignableFrom(type)) flags &= ~TypeFlags.CanBeTextValue; else if (type.IsAssignableFrom(typeof(XmlAttribute))) flags |= TypeFlags.CanBeAttributeValue; } else { kind = TypeKind.Class; baseType = type.BaseType; if (type.IsAbstract) flags |= TypeFlags.Abstract; } } else if (type.IsInterface) { kind = TypeKind.Void; flags |= TypeFlags.Unsupported; if (exception == null) { if (memberInfo == null) { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterface, type.FullName)); } else { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterfaceDetails, memberInfo.DeclaringType.FullName + "." + memberInfo.Name, type.FullName)); } } } else { kind = TypeKind.Void; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } // check to see if the type has public default constructor for classes if (kind == TypeKind.Class && !type.IsAbstract) { flags |= GetConstructorFlags(type, ref exception); } // check if a struct-like type is enumerable if (kind == TypeKind.Struct || kind == TypeKind.Class){ if (typeof(IEnumerable).IsAssignableFrom(type)) { arrayElementType = GetEnumeratorElementType(type, ref flags); kind = TypeKind.Enumerable; // GetEnumeratorElementType checks for the security attributes on the GetEnumerator(), Add() methods and Current property, // we need to check the MoveNext() and ctor methods for the security attribues flags |= GetConstructorFlags(type, ref exception); } } // typeDesc = new TypeDesc(type, CodeIdentifier.MakeValid(TypeName(type)), type.ToString(), kind, null, flags, null); typeDesc.Exception = exception; if (directReference && (typeDesc.IsClass || kind == TypeKind.Serializable)) typeDesc.CheckNeedConstructor(); if (typeDesc.IsUnsupported) { // return right away, do not check anything else return typeDesc; } typeDescs.Add(type, typeDesc); if (arrayElementType != null) { TypeDesc td = GetTypeDesc(arrayElementType, memberInfo, true, false); // explicitly disallow read-only elements, even if they are collections if (directReference && (td.IsCollection || td.IsEnumerable) && !td.IsPrimitive) { td.CheckNeedConstructor(); } typeDesc.ArrayElementTypeDesc = td; } if (baseType != null && baseType != typeof(object) && baseType != typeof(ValueType)) { typeDesc.BaseTypeDesc = GetTypeDesc(baseType, memberInfo, false, false); } if (type.IsNestedPublic) { for (Type t = type.DeclaringType; t != null && !t.ContainsGenericParameters; t = t.DeclaringType) GetTypeDesc(t, null, false); } return typeDesc; } internal static bool IsOptionalValue(Type type) { if (type.IsGenericType) { if (type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition()) return true; } return false; } // /* static string GetHash(string str) { MD5 md5 = MD5.Create(); string hash = Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(str)), 0, 6).Replace("+", "_P").Replace("/", "_S"); return hash; } */ // internal static string TypeName(Type t) { if (t.IsArray) { return "ArrayOf" + TypeName(t.GetElementType()); } else if (t.IsGenericType) { StringBuilder typeName = new StringBuilder(); StringBuilder ns = new StringBuilder(); string name = t.Name; int arity = name.IndexOf("`", StringComparison.Ordinal); if (arity >= 0) { name = name.Substring(0, arity); } typeName.Append(name); typeName.Append("Of"); Type[] arguments = t.GetGenericArguments(); for (int i = 0; i < arguments.Length; i++) { typeName.Append(TypeName(arguments[i])); ns.Append(arguments[i].Namespace); } // /* if (ns.Length > 0) { typeName.Append("_"); typeName.Append(GetHash(ns.ToString())); } */ return typeName.ToString(); } return t.Name; } internal static Type GetArrayElementType(Type type, string memberInfo) { if (type.IsArray) return type.GetElementType(); else if (typeof(ICollection).IsAssignableFrom(type)) return GetCollectionElementType(type, memberInfo); else if (typeof(IEnumerable).IsAssignableFrom(type)) { TypeFlags flags = TypeFlags.None; return GetEnumeratorElementType(type, ref flags); } else return null; } internal static MemberMapping[] GetAllMembers(StructMapping mapping) { if (mapping.BaseMapping == null) return mapping.Members; ArrayList list = new ArrayList(); GetAllMembers(mapping, list); return (MemberMapping[])list.ToArray(typeof(MemberMapping)); } internal static void GetAllMembers(StructMapping mapping, ArrayList list) { if (mapping.BaseMapping != null) { GetAllMembers(mapping.BaseMapping, list); } for (int i = 0; i < mapping.Members.Length; i++) { list.Add(mapping.Members[i]); } } static TypeFlags GetConstructorFlags(Type type, ref Exception exception) { ConstructorInfo ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null); if (ctor != null) { TypeFlags flags = TypeFlags.HasDefaultConstructor; if (!ctor.IsPublic) flags |= TypeFlags.CtorInaccessible; else { object[] attrs = ctor.GetCustomAttributes(typeof(ObsoleteAttribute), false); if (attrs != null && attrs.Length > 0) { ObsoleteAttribute obsolete = (ObsoleteAttribute)attrs[0]; if (obsolete.IsError) { flags |= TypeFlags.CtorInaccessible; } } } return flags; } return 0; } static Type GetEnumeratorElementType(Type type, ref TypeFlags flags) { if (typeof(IEnumerable).IsAssignableFrom(type)) { MethodInfo enumerator = type.GetMethod("GetEnumerator", new Type[0]); if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { // try generic implementation enumerator = null; foreach (MemberInfo member in type.GetMember("System.Collections.Generic.IEnumerable<*", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)) { enumerator = member as MethodInfo; if (enumerator != null && typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { // use the first one we find flags |= TypeFlags.GenericInterface; break; } else { enumerator = null; } } if (enumerator == null) { // and finally private interface implementation flags |= TypeFlags.UsePrivateImplementation; enumerator = type.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null); } } if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { return null; } XmlAttributes methodAttrs = new XmlAttributes(enumerator); if (methodAttrs.XmlIgnore) return null; PropertyInfo p = enumerator.ReturnType.GetProperty("Current"); Type currentType = (p == null ? typeof(object) : p.PropertyType); MethodInfo addMethod = type.GetMethod("Add", new Type[] { currentType }); if (addMethod == null && currentType != typeof(object)) { currentType = typeof(object); addMethod = type.GetMethod("Add", new Type[] { currentType }); } if (addMethod == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, currentType, "IEnumerable")); } return currentType; } else { return null; } } internal static PropertyInfo GetDefaultIndexer(Type type, string memberInfo){ if (typeof(IDictionary).IsAssignableFrom(type)) { if (memberInfo == null) { throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionary, type.FullName)); } else { throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionaryDetails, memberInfo, type.FullName)); } } MemberInfo[] defaultMembers = type.GetDefaultMembers(); PropertyInfo indexer = null; if (defaultMembers != null && defaultMembers.Length > 0) { for (Type t = type; t != null; t = t.BaseType) { for (int i = 0; i < defaultMembers.Length; i++) { if (defaultMembers[i] is PropertyInfo) { PropertyInfo defaultProp = (PropertyInfo)defaultMembers[i]; if (defaultProp.DeclaringType != t) continue; if (!defaultProp.CanRead) continue; MethodInfo getMethod = defaultProp.GetGetMethod(); ParameterInfo[] parameters = getMethod.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(int)) { indexer = defaultProp; break; } } } if (indexer != null) break; } } if (indexer == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoDefaultAccessors, type.FullName)); } MethodInfo addMethod = type.GetMethod("Add", new Type[] { indexer.PropertyType }); if (addMethod == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, indexer.PropertyType, "ICollection")); } return indexer; } static Type GetCollectionElementType(Type type, string memberInfo) { return GetDefaultIndexer(type, memberInfo).PropertyType; } static internal XmlQualifiedName ParseWsdlArrayType(string type, out string dims, XmlSchemaObject parent) { string ns; string name; int nsLen = type.LastIndexOf(':'); if (nsLen <= 0) { ns = ""; } else { ns = type.Substring(0, nsLen); } int nameLen = type.IndexOf('[', nsLen + 1); if (nameLen <= nsLen) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayTypeSyntax, type)); } name = type.Substring(nsLen + 1, nameLen - nsLen - 1); dims = type.Substring(nameLen); // parent is not null only in the case when we used XmlSchema.Read(), // in which case we need to fixup the wsdl:arayType attribute value while (parent != null) { if (parent.Namespaces != null) { string wsdlNs = (string)parent.Namespaces.Namespaces[ns]; if (wsdlNs != null) { ns = wsdlNs; break; } } parent = parent.Parent; } return new XmlQualifiedName(name, ns); } internal ICollection Types { get { return this.typeDescs.Keys; } } internal void AddTypeMapping(TypeMapping typeMapping) { typeMappings.Add(typeMapping); } internal ICollection TypeMappings { get { return typeMappings; } } internal static Hashtable PrimtiveTypes { get { return primitiveTypes; } } } internal class Soap { private Soap() {} internal const string Encoding = "http://schemas.xmlsoap.org/soap/encoding/"; internal const string UrType = "anyType"; internal const string Array = "Array"; internal const string ArrayType = "arrayType"; } internal class Soap12 { private Soap12() {} internal const string Encoding = "http://www.w3.org/2003/05/soap-encoding"; internal const string RpcNamespace = "http://www.w3.org/2003/05/soap-rpc"; internal const string RpcResult = "result"; } internal class Wsdl { private Wsdl() {} internal const string Namespace = "http://schemas.xmlsoap.org/wsdl/"; internal const string ArrayType = "arrayType"; } internal class UrtTypes { private UrtTypes() {} internal const string Namespace = "http://microsoft.com/wsdl/types/"; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml.Serialization { using System; using System.IO; using System.Reflection; using System.Collections; using System.Xml.Schema; using System.Xml; using System.Text; using System.ComponentModel; using System.CodeDom; using System.CodeDom.Compiler; using System.Xml.Serialization.Advanced; using System.Globalization; using System.Security.Cryptography; // These classes provide a higher level view on reflection specific to // Xml serialization, for example: // - allowing one to talk about types w/o having them compiled yet // - abstracting collections & arrays // - abstracting classes, structs, interfaces // - knowing about XSD primitives // - dealing with Serializable and xmlelement // and lots of other little details internal enum TypeKind { Root, Primitive, Enum, Struct, Class, Array, Collection, Enumerable, Void, Node, Attribute, Serializable } internal enum TypeFlags { None = 0x0, Abstract = 0x1, Reference = 0x2, Special = 0x4, CanBeAttributeValue = 0x8, CanBeTextValue = 0x10, CanBeElementValue = 0x20, HasCustomFormatter = 0x40, AmbiguousDataType = 0x80, IgnoreDefault = 0x200, HasIsEmpty = 0x400, HasDefaultConstructor = 0x800, XmlEncodingNotRequired = 0x1000, UseReflection = 0x4000, CollapseWhitespace = 0x8000, OptionalValue = 0x10000, CtorInaccessible = 0x20000, UsePrivateImplementation = 0x40000, GenericInterface = 0x80000, Unsupported = 0x100000, } internal class TypeDesc { string name; string fullName; string cSharpName; TypeDesc arrayElementTypeDesc; TypeDesc arrayTypeDesc; TypeDesc nullableTypeDesc; TypeKind kind; XmlSchemaType dataType; Type type; TypeDesc baseTypeDesc; TypeFlags flags; string formatterName; bool isXsdType; bool isMixed; MappedTypeDesc extendedType; int weight; Exception exception; internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, string formatterName) { this.name = name.Replace('+', '.'); this.fullName = fullName.Replace('+', '.'); this.kind = kind; this.baseTypeDesc = baseTypeDesc; this.flags = flags; this.isXsdType = kind == TypeKind.Primitive; if (this.isXsdType) this.weight = 1; else if (kind == TypeKind.Enum) this.weight = 2; else if (this.kind == TypeKind.Root) this.weight = -1; else this.weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1; this.dataType = dataType; this.formatterName = formatterName; } internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, dataType, kind, baseTypeDesc, flags, null) {} internal TypeDesc(string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, (XmlSchemaType)null, kind, baseTypeDesc, flags, null) {} internal TypeDesc(Type type, bool isXsdType, XmlSchemaType dataType, string formatterName, TypeFlags flags) : this(type.Name, type.FullName, dataType, TypeKind.Primitive, (TypeDesc)null, flags, formatterName) { this.isXsdType = isXsdType; this.type = type; } internal TypeDesc(Type type, string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, TypeDesc arrayElementTypeDesc) : this(name, fullName, null, kind, baseTypeDesc, flags, null) { this.arrayElementTypeDesc = arrayElementTypeDesc; this.type = type; } public override string ToString() { return fullName; } internal TypeFlags Flags { get { return flags; } } internal bool IsXsdType { get { return isXsdType; } } internal bool IsMappedType { get { return extendedType != null; } } internal MappedTypeDesc ExtendedType { get { return extendedType; } } internal string Name { get { return name; } } internal string FullName { get { return fullName; } } internal string CSharpName { get { if (cSharpName == null) { cSharpName = type == null ? CodeIdentifier.GetCSharpName(fullName) : CodeIdentifier.GetCSharpName(type); } return cSharpName; } } internal XmlSchemaType DataType { get { return dataType; } } internal Type Type { get { return type; } } internal string FormatterName { get { return formatterName; } } internal TypeKind Kind { get { return kind; } } internal bool IsValueType { get { return (flags & TypeFlags.Reference) == 0; } } internal bool CanBeAttributeValue { get { return (flags & TypeFlags.CanBeAttributeValue) != 0; } } internal bool XmlEncodingNotRequired { get { return (flags & TypeFlags.XmlEncodingNotRequired) != 0; } } internal bool CanBeElementValue { get { return (flags & TypeFlags.CanBeElementValue) != 0; } } internal bool CanBeTextValue { get { return (flags & TypeFlags.CanBeTextValue) != 0; } } internal bool IsMixed { get { return isMixed || CanBeTextValue; } set { isMixed = value; } } internal bool IsSpecial { get { return (flags & TypeFlags.Special) != 0; } } internal bool IsAmbiguousDataType { get { return (flags & TypeFlags.AmbiguousDataType) != 0; } } internal bool HasCustomFormatter { get { return (flags & TypeFlags.HasCustomFormatter) != 0; } } internal bool HasDefaultSupport { get { return (flags & TypeFlags.IgnoreDefault) == 0; } } internal bool HasIsEmpty { get { return (flags & TypeFlags.HasIsEmpty) != 0; } } internal bool CollapseWhitespace { get { return (flags & TypeFlags.CollapseWhitespace) != 0; } } internal bool HasDefaultConstructor { get { return (flags & TypeFlags.HasDefaultConstructor) != 0; } } internal bool IsUnsupported { get { return (flags & TypeFlags.Unsupported) != 0; } } internal bool IsGenericInterface { get { return (flags & TypeFlags.GenericInterface) != 0; } } internal bool IsPrivateImplementation { get { return (flags & TypeFlags.UsePrivateImplementation) != 0; } } internal bool CannotNew { get { return !HasDefaultConstructor || ConstructorInaccessible; } } internal bool IsAbstract { get { return (flags & TypeFlags.Abstract) != 0; } } internal bool IsOptionalValue { get { return (flags & TypeFlags.OptionalValue) != 0; } } internal bool UseReflection { get { return (flags & TypeFlags.UseReflection) != 0; } } internal bool IsVoid { get { return kind == TypeKind.Void; } } internal bool IsClass { get { return kind == TypeKind.Class; } } internal bool IsStructLike { get { return kind == TypeKind.Struct || kind == TypeKind.Class; } } internal bool IsArrayLike { get { return kind == TypeKind.Array || kind == TypeKind.Collection || kind == TypeKind.Enumerable; } } internal bool IsCollection { get { return kind == TypeKind.Collection; } } internal bool IsEnumerable { get { return kind == TypeKind.Enumerable; } } internal bool IsArray { get { return kind == TypeKind.Array; } } internal bool IsPrimitive { get { return kind == TypeKind.Primitive; } } internal bool IsEnum { get { return kind == TypeKind.Enum; } } internal bool IsNullable { get { return !IsValueType; } } internal bool IsRoot { get { return kind == TypeKind.Root; } } internal bool ConstructorInaccessible { get { return (flags & TypeFlags.CtorInaccessible) != 0; } } internal Exception Exception { get { return exception; } set { exception = value; } } internal TypeDesc GetNullableTypeDesc(Type type) { if (IsOptionalValue) return this; if (nullableTypeDesc == null) { nullableTypeDesc = new TypeDesc("NullableOf" + this.name, "System.Nullable`1[" + this.fullName + "]", null, TypeKind.Struct, this, this.flags | TypeFlags.OptionalValue, this.formatterName); nullableTypeDesc.type = type; } return nullableTypeDesc; } internal void CheckSupported() { if (IsUnsupported) { if (Exception != null) { throw Exception; } else { throw new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, FullName)); } } if (baseTypeDesc != null) baseTypeDesc.CheckSupported(); if (arrayElementTypeDesc != null) arrayElementTypeDesc.CheckSupported(); } internal void CheckNeedConstructor() { if (!IsValueType && !IsAbstract && !HasDefaultConstructor) { flags |= TypeFlags.Unsupported; this.exception = new InvalidOperationException(Res.GetString(Res.XmlConstructorInaccessible, FullName)); } } internal string ArrayLengthName { get { return kind == TypeKind.Array ? "Length" : "Count"; } } internal TypeDesc ArrayElementTypeDesc { get { return arrayElementTypeDesc; } set { arrayElementTypeDesc = value; } } internal int Weight { get { return weight; } } internal TypeDesc CreateArrayTypeDesc() { if (arrayTypeDesc == null) arrayTypeDesc = new TypeDesc(null, name + "[]", fullName + "[]", TypeKind.Array, null, TypeFlags.Reference|(flags & TypeFlags.UseReflection), this); return arrayTypeDesc; } internal TypeDesc CreateMappedTypeDesc(MappedTypeDesc extension) { TypeDesc newTypeDesc = new TypeDesc(extension.Name, extension.Name, null, this.kind, this.baseTypeDesc, this.flags, null); newTypeDesc.isXsdType = this.isXsdType; newTypeDesc.isMixed = this.isMixed; newTypeDesc.extendedType = extension; newTypeDesc.dataType = this.dataType; return newTypeDesc; } internal TypeDesc BaseTypeDesc { get { return baseTypeDesc; } set { baseTypeDesc = value; weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1; } } internal bool IsDerivedFrom(TypeDesc baseTypeDesc) { TypeDesc typeDesc = this; while (typeDesc != null) { if (typeDesc == baseTypeDesc) return true; typeDesc = typeDesc.BaseTypeDesc; } return baseTypeDesc.IsRoot; } internal static TypeDesc FindCommonBaseTypeDesc(TypeDesc[] typeDescs) { if (typeDescs.Length == 0) return null; TypeDesc leastDerivedTypeDesc = null; int leastDerivedLevel = int.MaxValue; for (int i = 0; i < typeDescs.Length; i++) { int derivationLevel = typeDescs[i].Weight; if (derivationLevel < leastDerivedLevel) { leastDerivedLevel = derivationLevel; leastDerivedTypeDesc = typeDescs[i]; } } while (leastDerivedTypeDesc != null) { int i; for (i = 0; i < typeDescs.Length; i++) { if (!typeDescs[i].IsDerivedFrom(leastDerivedTypeDesc)) break; } if (i == typeDescs.Length) break; leastDerivedTypeDesc = leastDerivedTypeDesc.BaseTypeDesc; } return leastDerivedTypeDesc; } } internal class TypeScope { Hashtable typeDescs = new Hashtable(); Hashtable arrayTypeDescs = new Hashtable(); ArrayList typeMappings = new ArrayList(); static Hashtable primitiveTypes = new Hashtable(); static Hashtable primitiveDataTypes = new Hashtable(); static NameTable primitiveNames = new NameTable(); static string[] unsupportedTypes = new string[] { "anyURI", "duration", "ENTITY", "ENTITIES", "gDay", "gMonth", "gMonthDay", "gYear", "gYearMonth", "ID", "IDREF", "IDREFS", "integer", "language", "negativeInteger", "nonNegativeInteger", "nonPositiveInteger", //"normalizedString", "NOTATION", "positiveInteger", "token" }; static TypeScope() { AddPrimitive(typeof(string), "string", "String", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); AddPrimitive(typeof(int), "int", "Int32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(bool), "boolean", "Boolean", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(short), "short", "Int16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(long), "long", "Int64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(float), "float", "Single", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(double), "double", "Double", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(decimal), "decimal", "Decimal", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(DateTime), "dateTime", "DateTime", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(XmlQualifiedName), "QName", "XmlQualifiedName", TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference); AddPrimitive(typeof(byte), "unsignedByte", "Byte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(SByte), "byte", "SByte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt16), "unsignedShort", "UInt16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt32), "unsignedInt", "UInt32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(UInt64), "unsignedLong", "UInt64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); // Types without direct mapping (ambigous) AddPrimitive(typeof(DateTime), "date", "Date", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(DateTime), "time", "Time", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddPrimitive(typeof(string), "Name", "XmlName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NCName", "XmlNCName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NMTOKEN", "XmlNmToken", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(string), "NMTOKENS", "XmlNmTokens", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddPrimitive(typeof(byte[]), "base64Binary", "ByteArrayBase64", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor); AddPrimitive(typeof(byte[]), "hexBinary", "ByteArrayHex", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor); // NOTE, [....]: byte[] can also be used to mean array of bytes. That datatype is not a primitive, so we // can't use the AmbiguousDataType mechanism. To get an array of bytes in literal XML, apply [XmlArray] or // [XmlArrayItem]. XmlSchemaPatternFacet guidPattern = new XmlSchemaPatternFacet(); guidPattern.Value = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"; AddNonXsdPrimitive(typeof(Guid), "guid", UrtTypes.Namespace, "Guid", new XmlQualifiedName("string", XmlSchema.Namespace), new XmlSchemaFacet[] { guidPattern }, TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.IgnoreDefault); AddNonXsdPrimitive(typeof(char), "char", UrtTypes.Namespace, "Char", new XmlQualifiedName("unsignedShort", XmlSchema.Namespace), new XmlSchemaFacet[0], TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.IgnoreDefault); AddSoapEncodedTypes(Soap.Encoding); // Unsuppoted types that we map to string, if in the future we decide // to add support for them we would need to create custom formatters for them // normalizedString is the only one unsuported type that suppose to preserve whitesapce AddPrimitive(typeof(string), "normalizedString", "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); for (int i = 0; i < unsupportedTypes.Length; i++) { AddPrimitive(typeof(string), unsupportedTypes[i], "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace); } } internal static bool IsKnownType(Type type) { if (type == typeof(object)) return true; if (type.IsEnum) return false; switch (Type.GetTypeCode(type)) { case TypeCode.String: return true; case TypeCode.Int32: return true; case TypeCode.Boolean: return true; case TypeCode.Int16: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; case TypeCode.Decimal: return true; case TypeCode.DateTime: return true; case TypeCode.Byte: return true; case TypeCode.SByte: return true; case TypeCode.UInt16: return true; case TypeCode.UInt32: return true; case TypeCode.UInt64: return true; case TypeCode.Char: return true; default: if (type == typeof(XmlQualifiedName)) return true; else if (type == typeof(byte[])) return true; else if (type == typeof(Guid)) return true; else if (type == typeof(XmlNode[])){ return true; } break; } return false; } static void AddSoapEncodedTypes(string ns) { AddSoapEncodedPrimitive(typeof(string), "normalizedString", ns, "String", new XmlQualifiedName("normalizedString", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor); for (int i = 0; i < unsupportedTypes.Length; i++) { AddSoapEncodedPrimitive(typeof(string), unsupportedTypes[i], ns, "String", new XmlQualifiedName(unsupportedTypes[i], XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace); } AddSoapEncodedPrimitive(typeof(string), "string", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(int), "int", ns, "Int32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(bool), "boolean", ns, "Boolean", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(short), "short", ns, "Int16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(long), "long", ns, "Int64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(float), "float", ns, "Single", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(double), "double", ns, "Double", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(decimal), "decimal", ns, "Decimal", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(DateTime), "dateTime", ns, "DateTime", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(XmlQualifiedName), "QName", ns, "XmlQualifiedName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(byte), "unsignedByte", ns, "Byte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(SByte), "byte", ns, "SByte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt16), "unsignedShort", ns, "UInt16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt32), "unsignedInt", ns, "UInt32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(UInt64), "unsignedLong", ns, "UInt64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired); // Types without direct mapping (ambigous) AddSoapEncodedPrimitive(typeof(DateTime), "date", ns, "Date", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(DateTime), "time", ns, "Time", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(string), "Name", ns, "XmlName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NCName", ns, "XmlNCName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NMTOKEN", ns, "XmlNmToken", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(string), "NMTOKENS", ns, "XmlNmTokens", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference); AddSoapEncodedPrimitive(typeof(byte[]), "base64Binary", ns, "ByteArrayBase64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(byte[]), "hexBinary", ns, "ByteArrayHex", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired); AddSoapEncodedPrimitive(typeof(string), "arrayCoordinate", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue); AddSoapEncodedPrimitive(typeof(byte[]), "base64", ns, "ByteArrayBase64", new XmlQualifiedName("base64Binary", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.IgnoreDefault | TypeFlags.Reference); } static void AddPrimitive(Type type, string dataTypeName, string formatterName, TypeFlags flags) { XmlSchemaSimpleType dataType = new XmlSchemaSimpleType(); dataType.Name = dataTypeName; TypeDesc typeDesc = new TypeDesc(type, true, dataType, formatterName, flags); if (primitiveTypes[type] == null) primitiveTypes.Add(type, typeDesc); primitiveDataTypes.Add(dataType, typeDesc); primitiveNames.Add(dataTypeName, XmlSchema.Namespace, typeDesc); } static void AddNonXsdPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, XmlSchemaFacet[] facets, TypeFlags flags) { XmlSchemaSimpleType dataType = new XmlSchemaSimpleType(); dataType.Name = dataTypeName; XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction(); restriction.BaseTypeName = baseTypeName; foreach (XmlSchemaFacet facet in facets) { restriction.Facets.Add(facet); } dataType.Content = restriction; TypeDesc typeDesc = new TypeDesc(type, false, dataType, formatterName, flags); if (primitiveTypes[type] == null) primitiveTypes.Add(type, typeDesc); primitiveDataTypes.Add(dataType, typeDesc); primitiveNames.Add(dataTypeName, ns, typeDesc); } static void AddSoapEncodedPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, TypeFlags flags) { AddNonXsdPrimitive(type, dataTypeName, ns, formatterName, baseTypeName, new XmlSchemaFacet[0], flags); } internal TypeDesc GetTypeDesc(string name, string ns) { return GetTypeDesc(name, ns, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.CanBeAttributeValue); } internal TypeDesc GetTypeDesc(string name, string ns, TypeFlags flags) { TypeDesc typeDesc = (TypeDesc)primitiveNames[name, ns]; if (typeDesc != null) { if ((typeDesc.Flags & flags) != 0) { return typeDesc; } } return null; } internal TypeDesc GetTypeDesc(XmlSchemaSimpleType dataType) { return (TypeDesc)primitiveDataTypes[dataType]; } internal TypeDesc GetTypeDesc(Type type) { return GetTypeDesc(type, null, true, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source) { return GetTypeDesc(type, source, true, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference) { return GetTypeDesc(type, source, directReference, true); } internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference, bool throwOnError) { if (type.ContainsGenericParameters) { throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedOpenGenericType, type.ToString())); } TypeDesc typeDesc = (TypeDesc)primitiveTypes[type]; if (typeDesc == null) { typeDesc = (TypeDesc)typeDescs[type]; if (typeDesc == null) { typeDesc = ImportTypeDesc(type, source, directReference); } } if (throwOnError) typeDesc.CheckSupported(); return typeDesc; } internal TypeDesc GetArrayTypeDesc(Type type) { TypeDesc typeDesc = (TypeDesc) arrayTypeDescs[type]; if (typeDesc == null) { typeDesc = GetTypeDesc(type); if (!typeDesc.IsArrayLike) typeDesc = ImportTypeDesc(type, null, false); typeDesc.CheckSupported(); arrayTypeDescs.Add(type, typeDesc); } return typeDesc; } internal TypeMapping GetTypeMappingFromTypeDesc(TypeDesc typeDesc){ foreach(TypeMapping typeMapping in TypeMappings){ if (typeMapping.TypeDesc == typeDesc) return typeMapping; } return null; } internal Type GetTypeFromTypeDesc(TypeDesc typeDesc){ if (typeDesc.Type != null) return typeDesc.Type; foreach(DictionaryEntry de in typeDescs){ if (de.Value == typeDesc) return de.Key as Type; } return null; } TypeDesc ImportTypeDesc(Type type, MemberInfo memberInfo, bool directReference) { TypeDesc typeDesc = null; TypeKind kind; Type arrayElementType = null; Type baseType = null; TypeFlags flags = 0; Exception exception = null; if (!type.IsPublic && !type.IsNestedPublic) { flags |= TypeFlags.Unsupported; exception = new InvalidOperationException(Res.GetString(Res.XmlTypeInaccessible, type.FullName)); } else if (type.IsAbstract && type.IsSealed) { flags |= TypeFlags.Unsupported; exception = new InvalidOperationException(Res.GetString(Res.XmlTypeStatic, type.FullName)); } if (DynamicAssemblies.IsTypeDynamic(type)){ flags |= TypeFlags.UseReflection; } if (!type.IsValueType) flags |= TypeFlags.Reference; if (type == typeof(object)) { kind = TypeKind.Root; flags |= TypeFlags.HasDefaultConstructor; } else if (type == typeof(ValueType)) { kind = TypeKind.Enum; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } else if (type == typeof(void)) { kind = TypeKind.Void; } else if (typeof(IXmlSerializable).IsAssignableFrom(type)) { // kind = TypeKind.Serializable; flags |= TypeFlags.Special | TypeFlags.CanBeElementValue; flags |= GetConstructorFlags(type, ref exception); } else if (type.IsArray) { kind = TypeKind.Array; if (type.GetArrayRank() > 1) { flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedRank, type.FullName)); } } arrayElementType = type.GetElementType(); flags |= TypeFlags.HasDefaultConstructor; } else if (typeof(ICollection).IsAssignableFrom(type)) { kind = TypeKind.Collection; arrayElementType = GetCollectionElementType(type, memberInfo == null ? null : memberInfo.DeclaringType.FullName + "." + memberInfo.Name); flags |= GetConstructorFlags(type, ref exception); } else if (type == typeof(XmlQualifiedName)) { kind = TypeKind.Primitive; } else if (type.IsPrimitive) { kind = TypeKind.Primitive; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } else if (type.IsEnum) { kind = TypeKind.Enum; } else if (type.IsValueType) { kind = TypeKind.Struct; if (IsOptionalValue(type)) { baseType = type.GetGenericArguments()[0]; flags |= TypeFlags.OptionalValue; } else { baseType = type.BaseType; } if (type.IsAbstract) flags |= TypeFlags.Abstract; } else if (type.IsClass) { if (type == typeof(XmlAttribute)) { kind = TypeKind.Attribute; flags |= TypeFlags.Special | TypeFlags.CanBeAttributeValue; } else if (typeof(XmlNode).IsAssignableFrom(type)) { kind = TypeKind.Node; baseType = type.BaseType; flags |= TypeFlags.Special | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue; if (typeof(XmlText).IsAssignableFrom(type)) flags &= ~TypeFlags.CanBeElementValue; else if (typeof(XmlElement).IsAssignableFrom(type)) flags &= ~TypeFlags.CanBeTextValue; else if (type.IsAssignableFrom(typeof(XmlAttribute))) flags |= TypeFlags.CanBeAttributeValue; } else { kind = TypeKind.Class; baseType = type.BaseType; if (type.IsAbstract) flags |= TypeFlags.Abstract; } } else if (type.IsInterface) { kind = TypeKind.Void; flags |= TypeFlags.Unsupported; if (exception == null) { if (memberInfo == null) { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterface, type.FullName)); } else { exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterfaceDetails, memberInfo.DeclaringType.FullName + "." + memberInfo.Name, type.FullName)); } } } else { kind = TypeKind.Void; flags |= TypeFlags.Unsupported; if (exception == null) { exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName)); } } // check to see if the type has public default constructor for classes if (kind == TypeKind.Class && !type.IsAbstract) { flags |= GetConstructorFlags(type, ref exception); } // check if a struct-like type is enumerable if (kind == TypeKind.Struct || kind == TypeKind.Class){ if (typeof(IEnumerable).IsAssignableFrom(type)) { arrayElementType = GetEnumeratorElementType(type, ref flags); kind = TypeKind.Enumerable; // GetEnumeratorElementType checks for the security attributes on the GetEnumerator(), Add() methods and Current property, // we need to check the MoveNext() and ctor methods for the security attribues flags |= GetConstructorFlags(type, ref exception); } } // typeDesc = new TypeDesc(type, CodeIdentifier.MakeValid(TypeName(type)), type.ToString(), kind, null, flags, null); typeDesc.Exception = exception; if (directReference && (typeDesc.IsClass || kind == TypeKind.Serializable)) typeDesc.CheckNeedConstructor(); if (typeDesc.IsUnsupported) { // return right away, do not check anything else return typeDesc; } typeDescs.Add(type, typeDesc); if (arrayElementType != null) { TypeDesc td = GetTypeDesc(arrayElementType, memberInfo, true, false); // explicitly disallow read-only elements, even if they are collections if (directReference && (td.IsCollection || td.IsEnumerable) && !td.IsPrimitive) { td.CheckNeedConstructor(); } typeDesc.ArrayElementTypeDesc = td; } if (baseType != null && baseType != typeof(object) && baseType != typeof(ValueType)) { typeDesc.BaseTypeDesc = GetTypeDesc(baseType, memberInfo, false, false); } if (type.IsNestedPublic) { for (Type t = type.DeclaringType; t != null && !t.ContainsGenericParameters; t = t.DeclaringType) GetTypeDesc(t, null, false); } return typeDesc; } internal static bool IsOptionalValue(Type type) { if (type.IsGenericType) { if (type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition()) return true; } return false; } // /* static string GetHash(string str) { MD5 md5 = MD5.Create(); string hash = Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(str)), 0, 6).Replace("+", "_P").Replace("/", "_S"); return hash; } */ // internal static string TypeName(Type t) { if (t.IsArray) { return "ArrayOf" + TypeName(t.GetElementType()); } else if (t.IsGenericType) { StringBuilder typeName = new StringBuilder(); StringBuilder ns = new StringBuilder(); string name = t.Name; int arity = name.IndexOf("`", StringComparison.Ordinal); if (arity >= 0) { name = name.Substring(0, arity); } typeName.Append(name); typeName.Append("Of"); Type[] arguments = t.GetGenericArguments(); for (int i = 0; i < arguments.Length; i++) { typeName.Append(TypeName(arguments[i])); ns.Append(arguments[i].Namespace); } // /* if (ns.Length > 0) { typeName.Append("_"); typeName.Append(GetHash(ns.ToString())); } */ return typeName.ToString(); } return t.Name; } internal static Type GetArrayElementType(Type type, string memberInfo) { if (type.IsArray) return type.GetElementType(); else if (typeof(ICollection).IsAssignableFrom(type)) return GetCollectionElementType(type, memberInfo); else if (typeof(IEnumerable).IsAssignableFrom(type)) { TypeFlags flags = TypeFlags.None; return GetEnumeratorElementType(type, ref flags); } else return null; } internal static MemberMapping[] GetAllMembers(StructMapping mapping) { if (mapping.BaseMapping == null) return mapping.Members; ArrayList list = new ArrayList(); GetAllMembers(mapping, list); return (MemberMapping[])list.ToArray(typeof(MemberMapping)); } internal static void GetAllMembers(StructMapping mapping, ArrayList list) { if (mapping.BaseMapping != null) { GetAllMembers(mapping.BaseMapping, list); } for (int i = 0; i < mapping.Members.Length; i++) { list.Add(mapping.Members[i]); } } static TypeFlags GetConstructorFlags(Type type, ref Exception exception) { ConstructorInfo ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null); if (ctor != null) { TypeFlags flags = TypeFlags.HasDefaultConstructor; if (!ctor.IsPublic) flags |= TypeFlags.CtorInaccessible; else { object[] attrs = ctor.GetCustomAttributes(typeof(ObsoleteAttribute), false); if (attrs != null && attrs.Length > 0) { ObsoleteAttribute obsolete = (ObsoleteAttribute)attrs[0]; if (obsolete.IsError) { flags |= TypeFlags.CtorInaccessible; } } } return flags; } return 0; } static Type GetEnumeratorElementType(Type type, ref TypeFlags flags) { if (typeof(IEnumerable).IsAssignableFrom(type)) { MethodInfo enumerator = type.GetMethod("GetEnumerator", new Type[0]); if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { // try generic implementation enumerator = null; foreach (MemberInfo member in type.GetMember("System.Collections.Generic.IEnumerable<*", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)) { enumerator = member as MethodInfo; if (enumerator != null && typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { // use the first one we find flags |= TypeFlags.GenericInterface; break; } else { enumerator = null; } } if (enumerator == null) { // and finally private interface implementation flags |= TypeFlags.UsePrivateImplementation; enumerator = type.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null); } } if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) { return null; } XmlAttributes methodAttrs = new XmlAttributes(enumerator); if (methodAttrs.XmlIgnore) return null; PropertyInfo p = enumerator.ReturnType.GetProperty("Current"); Type currentType = (p == null ? typeof(object) : p.PropertyType); MethodInfo addMethod = type.GetMethod("Add", new Type[] { currentType }); if (addMethod == null && currentType != typeof(object)) { currentType = typeof(object); addMethod = type.GetMethod("Add", new Type[] { currentType }); } if (addMethod == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, currentType, "IEnumerable")); } return currentType; } else { return null; } } internal static PropertyInfo GetDefaultIndexer(Type type, string memberInfo){ if (typeof(IDictionary).IsAssignableFrom(type)) { if (memberInfo == null) { throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionary, type.FullName)); } else { throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionaryDetails, memberInfo, type.FullName)); } } MemberInfo[] defaultMembers = type.GetDefaultMembers(); PropertyInfo indexer = null; if (defaultMembers != null && defaultMembers.Length > 0) { for (Type t = type; t != null; t = t.BaseType) { for (int i = 0; i < defaultMembers.Length; i++) { if (defaultMembers[i] is PropertyInfo) { PropertyInfo defaultProp = (PropertyInfo)defaultMembers[i]; if (defaultProp.DeclaringType != t) continue; if (!defaultProp.CanRead) continue; MethodInfo getMethod = defaultProp.GetGetMethod(); ParameterInfo[] parameters = getMethod.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(int)) { indexer = defaultProp; break; } } } if (indexer != null) break; } } if (indexer == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoDefaultAccessors, type.FullName)); } MethodInfo addMethod = type.GetMethod("Add", new Type[] { indexer.PropertyType }); if (addMethod == null) { throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, indexer.PropertyType, "ICollection")); } return indexer; } static Type GetCollectionElementType(Type type, string memberInfo) { return GetDefaultIndexer(type, memberInfo).PropertyType; } static internal XmlQualifiedName ParseWsdlArrayType(string type, out string dims, XmlSchemaObject parent) { string ns; string name; int nsLen = type.LastIndexOf(':'); if (nsLen <= 0) { ns = ""; } else { ns = type.Substring(0, nsLen); } int nameLen = type.IndexOf('[', nsLen + 1); if (nameLen <= nsLen) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayTypeSyntax, type)); } name = type.Substring(nsLen + 1, nameLen - nsLen - 1); dims = type.Substring(nameLen); // parent is not null only in the case when we used XmlSchema.Read(), // in which case we need to fixup the wsdl:arayType attribute value while (parent != null) { if (parent.Namespaces != null) { string wsdlNs = (string)parent.Namespaces.Namespaces[ns]; if (wsdlNs != null) { ns = wsdlNs; break; } } parent = parent.Parent; } return new XmlQualifiedName(name, ns); } internal ICollection Types { get { return this.typeDescs.Keys; } } internal void AddTypeMapping(TypeMapping typeMapping) { typeMappings.Add(typeMapping); } internal ICollection TypeMappings { get { return typeMappings; } } internal static Hashtable PrimtiveTypes { get { return primitiveTypes; } } } internal class Soap { private Soap() {} internal const string Encoding = "http://schemas.xmlsoap.org/soap/encoding/"; internal const string UrType = "anyType"; internal const string Array = "Array"; internal const string ArrayType = "arrayType"; } internal class Soap12 { private Soap12() {} internal const string Encoding = "http://www.w3.org/2003/05/soap-encoding"; internal const string RpcNamespace = "http://www.w3.org/2003/05/soap-rpc"; internal const string RpcResult = "result"; } internal class Wsdl { private Wsdl() {} internal const string Namespace = "http://schemas.xmlsoap.org/wsdl/"; internal const string ArrayType = "arrayType"; } internal class UrtTypes { private UrtTypes() {} internal const string Namespace = "http://microsoft.com/wsdl/types/"; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- processwaithandle.cs
- LowerCaseStringConverter.cs
- ApplicationContext.cs
- ConfigurationSettings.cs
- ProfileService.cs
- SubpageParagraph.cs
- X509Chain.cs
- HtmlElementErrorEventArgs.cs
- WaitForChangedResult.cs
- TextEndOfLine.cs
- Vector3DCollectionConverter.cs
- IItemProperties.cs
- ICspAsymmetricAlgorithm.cs
- DetailsView.cs
- WindowsSlider.cs
- XmlReader.cs
- ObjectDataProvider.cs
- EditingMode.cs
- RedirectionProxy.cs
- CodeConstructor.cs
- CustomPopupPlacement.cs
- InkCanvasFeedbackAdorner.cs
- SelectionListDesigner.cs
- CryptoApi.cs
- CodeTypeReferenceSerializer.cs
- ConsoleKeyInfo.cs
- CodeTypeDeclarationCollection.cs
- ListViewItemEventArgs.cs
- CheckBoxField.cs
- DefaultEventAttribute.cs
- Predicate.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- ToolBarPanel.cs
- KeyProperty.cs
- PathFigureCollectionConverter.cs
- MouseBinding.cs
- HttpCookieCollection.cs
- StylusOverProperty.cs
- MimePart.cs
- CqlErrorHelper.cs
- KerberosReceiverSecurityToken.cs
- ServiceDeploymentInfo.cs
- BitmapEffectInput.cs
- GenericIdentity.cs
- CmsUtils.cs
- recordstatescratchpad.cs
- ObjectDataSourceDisposingEventArgs.cs
- ComAdminWrapper.cs
- SafeHandles.cs
- DataGridColumnStyleMappingNameEditor.cs
- Point3DCollectionValueSerializer.cs
- ListenerPerfCounters.cs
- DateTimeSerializationSection.cs
- PageParser.cs
- AssemblyAttributesGoHere.cs
- HtmlElement.cs
- Matrix3DStack.cs
- MenuRendererClassic.cs
- PropertyBuilder.cs
- HttpListenerRequest.cs
- ClrProviderManifest.cs
- SiteMapHierarchicalDataSourceView.cs
- ConfigsHelper.cs
- Properties.cs
- SimpleTextLine.cs
- invalidudtexception.cs
- DbConnectionOptions.cs
- InternalsVisibleToAttribute.cs
- C14NUtil.cs
- DataSourceView.cs
- NumberFormatter.cs
- DesignerSerializerAttribute.cs
- SqlBulkCopyColumnMapping.cs
- DocumentViewerHelper.cs
- _LocalDataStore.cs
- ExpressionEditorAttribute.cs
- Utility.cs
- HttpModule.cs
- COM2EnumConverter.cs
- ImageSource.cs
- WorkflowMarkupSerializationProvider.cs
- ColumnPropertiesGroup.cs
- DecoderNLS.cs
- WhitespaceRuleLookup.cs
- SerialPort.cs
- DataObject.cs
- ChangeInterceptorAttribute.cs
- EditCommandColumn.cs
- MetadataUtil.cs
- CssStyleCollection.cs
- CacheRequest.cs
- ToolboxDataAttribute.cs
- HtmlTernaryTree.cs
- NoneExcludedImageIndexConverter.cs
- GlyphsSerializer.cs
- Visual3DCollection.cs
- ToolStripSeparator.cs
- XmlSignificantWhitespace.cs
- GetWinFXPath.cs
- CachedRequestParams.cs