Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Serialization / SoapReflectionImporter.cs / 1305376 / SoapReflectionImporter.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml.Serialization { using System.Reflection; using System; using System.Globalization; using System.Xml.Schema; using System.Collections; using System.ComponentModel; using System.Threading; ////// /// public class SoapReflectionImporter { TypeScope typeScope; SoapAttributeOverrides attributeOverrides; NameTable types = new NameTable(); // xmltypename + xmlns -> Mapping NameTable nullables = new NameTable(); // xmltypename + xmlns -> NullableMapping StructMapping root; string defaultNs; ModelScope modelScope; ///[To be supplied.] ////// /// public SoapReflectionImporter() : this(null, null) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(string defaultNamespace) : this(null, defaultNamespace) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(SoapAttributeOverrides attributeOverrides) : this(attributeOverrides, null) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(SoapAttributeOverrides attributeOverrides, string defaultNamespace) { if (defaultNamespace == null) defaultNamespace = String.Empty; if (attributeOverrides == null) attributeOverrides = new SoapAttributeOverrides(); this.attributeOverrides = attributeOverrides; this.defaultNs = defaultNamespace; this.typeScope = new TypeScope(); this.modelScope = new ModelScope(this.typeScope); } ///[To be supplied.] ////// /// public void IncludeTypes(ICustomAttributeProvider provider) { IncludeTypes(provider, new RecursionLimiter()); } void IncludeTypes(ICustomAttributeProvider provider, RecursionLimiter limiter) { object[] attrs = provider.GetCustomAttributes(typeof(SoapIncludeAttribute), false); for (int i = 0; i < attrs.Length; i++) { IncludeType(((SoapIncludeAttribute)attrs[i]).Type, limiter); } } ///[To be supplied.] ////// /// public void IncludeType(Type type) { IncludeType(type, new RecursionLimiter()); } void IncludeType(Type type, RecursionLimiter limiter) { ImportTypeMapping(modelScope.GetTypeModel(type), limiter); } ///[To be supplied.] ////// /// public XmlTypeMapping ImportTypeMapping(Type type) { return ImportTypeMapping(type, null); } ///[To be supplied.] ////// /// public XmlTypeMapping ImportTypeMapping(Type type, string defaultNamespace) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Mapping = ImportTypeMapping(modelScope.GetTypeModel(type), new RecursionLimiter()); element.Name = element.Mapping.DefaultElementName; element.Namespace = element.Mapping.Namespace == null ? defaultNamespace : element.Mapping.Namespace; element.Form = XmlSchemaForm.Qualified; XmlTypeMapping xmlMapping = new XmlTypeMapping(typeScope, element); xmlMapping.SetKeyInternal(XmlMapping.GenerateKey(type, null, defaultNamespace)); xmlMapping.IsSoap = true; xmlMapping.GenerateSerializer = true; return xmlMapping; } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members) { return ImportMembersMapping(elementName, ns, members, true, true, false); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors) { return ImportMembersMapping(elementName, ns, members, hasWrapperElement, writeAccessors, false); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate) { return ImportMembersMapping(elementName, ns, members, hasWrapperElement, writeAccessors, validate, XmlMappingAccess.Read | XmlMappingAccess.Write); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate, XmlMappingAccess access) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = elementName == null || elementName.Length == 0 ? elementName : XmlConvert.EncodeLocalName(elementName); element.Mapping = ImportMembersMapping(members, ns, hasWrapperElement, writeAccessors, validate, new RecursionLimiter()); element.Mapping.TypeName = elementName; element.Namespace = element.Mapping.Namespace == null ? ns : element.Mapping.Namespace; element.Form = XmlSchemaForm.Qualified; XmlMembersMapping xmlMapping = new XmlMembersMapping(typeScope, element, access); xmlMapping.IsSoap = true; xmlMapping.GenerateSerializer = true; return xmlMapping; } Exception ReflectionException(string context, Exception e) { return new InvalidOperationException(Res.GetString(Res.XmlReflectionError, context), e); } SoapAttributes GetAttributes(Type type) { SoapAttributes attrs = attributeOverrides[type]; if (attrs != null) return attrs; return new SoapAttributes(type); } SoapAttributes GetAttributes(MemberInfo memberInfo) { SoapAttributes attrs = attributeOverrides[memberInfo.DeclaringType, memberInfo.Name]; if (attrs != null) return attrs; return new SoapAttributes(memberInfo); } TypeMapping ImportTypeMapping(TypeModel model, RecursionLimiter limiter) { return ImportTypeMapping(model, String.Empty, limiter); } TypeMapping ImportTypeMapping(TypeModel model, string dataType, RecursionLimiter limiter) { if (dataType.Length > 0) { if (!model.TypeDesc.IsPrimitive) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDataTypeUsage, dataType, "SoapElementAttribute.DataType")); } TypeDesc td = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); if (td == null) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidXsdDataType, dataType, "SoapElementAttribute.DataType", new XmlQualifiedName(dataType, XmlSchema.Namespace).ToString())); } if (model.TypeDesc.FullName != td.FullName) { throw new InvalidOperationException(Res.GetString(Res.XmlDataTypeMismatch, dataType, "SoapElementAttribute.DataType", model.TypeDesc.FullName)); } } SoapAttributes a = GetAttributes(model.Type); if ((a.SoapFlags & ~SoapAttributeFlags.Type) != 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidTypeAttributes, model.Type.FullName)); switch (model.TypeDesc.Kind) { case TypeKind.Enum: return ImportEnumMapping((EnumModel)model); case TypeKind.Primitive: return ImportPrimitiveMapping((PrimitiveModel)model, dataType); case TypeKind.Array: case TypeKind.Collection: case TypeKind.Enumerable: return ImportArrayLikeMapping((ArrayModel)model, limiter); case TypeKind.Root: case TypeKind.Class: case TypeKind.Struct: if (model.TypeDesc.IsOptionalValue) { TypeDesc baseTypeDesc = model.TypeDesc.BaseTypeDesc; SoapAttributes baseAttributes = GetAttributes(baseTypeDesc.Type); string typeNs = defaultNs; if (baseAttributes.SoapType != null && baseAttributes.SoapType.Namespace != null) typeNs = baseAttributes.SoapType.Namespace; TypeDesc valueTypeDesc = string.IsNullOrEmpty(dataType) ? model.TypeDesc.BaseTypeDesc : typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); string xsdTypeName = string.IsNullOrEmpty(dataType) ? model.TypeDesc.BaseTypeDesc.Name : dataType; TypeMapping baseMapping = GetTypeMapping(xsdTypeName, typeNs, valueTypeDesc); if (baseMapping == null) baseMapping = ImportTypeMapping(modelScope.GetTypeModel(baseTypeDesc.Type), dataType, limiter); return CreateNullableMapping(baseMapping, model.TypeDesc.Type); } else { return ImportStructLikeMapping((StructModel)model, limiter); } default: throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedSoapTypeKind, model.TypeDesc.FullName)); } } StructMapping CreateRootMapping() { TypeDesc typeDesc = typeScope.GetTypeDesc(typeof(object)); StructMapping mapping = new StructMapping(); mapping.IsSoap = true; mapping.TypeDesc = typeDesc; mapping.Members = new MemberMapping[0]; mapping.IncludeInSchema = false; mapping.TypeName = Soap.UrType; mapping.Namespace = XmlSchema.Namespace; return mapping; } StructMapping GetRootMapping() { if (root == null) { root = CreateRootMapping(); typeScope.AddTypeMapping(root); } return root; } TypeMapping GetTypeMapping(string typeName, string ns, TypeDesc typeDesc) { TypeMapping mapping = (TypeMapping)types[typeName, ns]; if (mapping == null) return null; if (mapping.TypeDesc != typeDesc) throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, mapping.TypeDesc.FullName, typeName, ns)); return mapping; } NullableMapping CreateNullableMapping(TypeMapping baseMapping, Type type) { TypeDesc typeDesc = baseMapping.TypeDesc.GetNullableTypeDesc(type); TypeMapping existingMapping = (TypeMapping)nullables[baseMapping.TypeName, baseMapping.Namespace]; NullableMapping mapping; if (existingMapping != null) { if (existingMapping is NullableMapping) { mapping = (NullableMapping)existingMapping; if (mapping.BaseMapping is PrimitiveMapping && baseMapping is PrimitiveMapping) return mapping; else if (mapping.BaseMapping == baseMapping) { return mapping; } else { throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace)); } } else if (!(baseMapping is PrimitiveMapping)){ throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace)); } } mapping = new NullableMapping(); mapping.BaseMapping = baseMapping; mapping.TypeDesc = typeDesc; mapping.TypeName = baseMapping.TypeName; mapping.Namespace = baseMapping.Namespace; mapping.IncludeInSchema = false; //baseMapping.IncludeInSchema; nullables.Add(baseMapping.TypeName, mapping.Namespace, mapping); typeScope.AddTypeMapping(mapping); return mapping; } StructMapping ImportStructLikeMapping(StructModel model, RecursionLimiter limiter) { if (model.TypeDesc.Kind == TypeKind.Root) return GetRootMapping(); SoapAttributes a = GetAttributes(model.Type); string typeNs = defaultNs; if (a.SoapType != null && a.SoapType.Namespace != null) typeNs = a.SoapType.Namespace; string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name); typeName = XmlConvert.EncodeLocalName(typeName); StructMapping mapping = (StructMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc); if (mapping == null) { mapping = new StructMapping(); mapping.IsSoap = true; mapping.TypeDesc = model.TypeDesc; mapping.Namespace = typeNs; mapping.TypeName = typeName; if (a.SoapType != null) mapping.IncludeInSchema = a.SoapType.IncludeInSchema; typeScope.AddTypeMapping(mapping); types.Add(typeName, typeNs, mapping); if (limiter.IsExceededLimit) { limiter.DeferredWorkItems.Add(new ImportStructWorkItem(model, mapping)); return mapping; } limiter.Depth++; InitializeStructMembers(mapping, model, limiter); while (limiter.DeferredWorkItems.Count > 0) { int index = limiter.DeferredWorkItems.Count - 1; ImportStructWorkItem item = limiter.DeferredWorkItems[index]; if (InitializeStructMembers(item.Mapping, item.Model, limiter)) { // // if InitializeStructMembers returns true, then there were *no* chages to the DeferredWorkItems // #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (index != limiter.DeferredWorkItems.Count - 1) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "DeferredWorkItems.Count have changed")); if (item != limiter.DeferredWorkItems[index]) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "DeferredWorkItems.Top have changed")); #endif // Remove the last work item limiter.DeferredWorkItems.RemoveAt(index); } } limiter.Depth--; } return mapping; } bool InitializeStructMembers(StructMapping mapping, StructModel model, RecursionLimiter limiter) { if (mapping.IsFullyInitialized) return true; if (model.TypeDesc.BaseTypeDesc != null) { StructMapping baseMapping = ImportStructLikeMapping((StructModel)modelScope.GetTypeModel(model.Type.BaseType, false), limiter); // check to see if the import of the baseMapping was deffered int baseIndex = limiter.DeferredWorkItems.IndexOf(mapping.BaseMapping); if (baseIndex < 0) { mapping.BaseMapping = baseMapping; } else { // the import of the baseMapping was deffered, make sure that the derived mappings is deffered as well if (!limiter.DeferredWorkItems.Contains(mapping)) { limiter.DeferredWorkItems.Add(new ImportStructWorkItem(model, mapping)); } // make sure that baseMapping get processed before the derived int top = limiter.DeferredWorkItems.Count-1; if (baseIndex < top) { ImportStructWorkItem baseMappingWorkItem = limiter.DeferredWorkItems[baseIndex]; limiter.DeferredWorkItems[baseIndex] = limiter.DeferredWorkItems[top]; limiter.DeferredWorkItems[top] = baseMappingWorkItem; } return false; } } ArrayList members = new ArrayList(); foreach (MemberInfo memberInfo in model.GetMemberInfos()) { if ((memberInfo.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0) continue; SoapAttributes memberAttrs = GetAttributes(memberInfo); if (memberAttrs.SoapIgnore) continue; FieldModel fieldModel = model.GetFieldModel(memberInfo); if (fieldModel == null) continue; MemberMapping member = ImportFieldMapping(fieldModel, memberAttrs, mapping.Namespace, limiter); if (member == null) continue; if (!member.TypeDesc.IsPrimitive && !member.TypeDesc.IsEnum && !member.TypeDesc.IsOptionalValue) { if (model.TypeDesc.IsValueType) throw new NotSupportedException(Res.GetString(Res.XmlRpcRefsInValueType, model.TypeDesc.FullName)); if (member.TypeDesc.IsValueType) throw new NotSupportedException(Res.GetString(Res.XmlRpcNestedValueType, member.TypeDesc.FullName)); } if (mapping.BaseMapping != null) { if (mapping.BaseMapping.Declares(member, mapping.TypeName)) continue; } members.Add(member); } mapping.Members = (MemberMapping[])members.ToArray(typeof(MemberMapping)); if (mapping.BaseMapping == null) mapping.BaseMapping = GetRootMapping(); IncludeTypes(model.Type, limiter); return true; } ArrayMapping ImportArrayLikeMapping(ArrayModel model, RecursionLimiter limiter) { ArrayMapping mapping = new ArrayMapping(); mapping.IsSoap = true; TypeMapping itemTypeMapping = ImportTypeMapping(model.Element, limiter); if (itemTypeMapping.TypeDesc.IsValueType && !itemTypeMapping.TypeDesc.IsPrimitive && !itemTypeMapping.TypeDesc.IsEnum) throw new NotSupportedException(Res.GetString(Res.XmlRpcArrayOfValueTypes, model.TypeDesc.FullName)); mapping.TypeDesc = model.TypeDesc; mapping.Elements = new ElementAccessor[] { CreateElementAccessor(itemTypeMapping, mapping.Namespace) }; SetArrayMappingType(mapping); // in the case of an ArrayMapping we can have more that one mapping correspond to a type // examples of that are ArrayList and object[] both will map tp ArrayOfur-type // so we create a link list for all mappings of the same XSD type ArrayMapping existingMapping = (ArrayMapping)types[mapping.TypeName, mapping.Namespace]; if (existingMapping != null) { ArrayMapping first = existingMapping; while (existingMapping != null) { if (existingMapping.TypeDesc == model.TypeDesc) return existingMapping; existingMapping = existingMapping.Next; } mapping.Next = first; types[mapping.TypeName, mapping.Namespace] = mapping; return mapping; } typeScope.AddTypeMapping(mapping); types.Add(mapping.TypeName, mapping.Namespace, mapping); IncludeTypes(model.Type); return mapping; } // void SetArrayMappingType(ArrayMapping mapping) { bool useDefaultNs = false; string itemTypeName; string itemTypeNamespace; TypeMapping itemTypeMapping; if (mapping.Elements.Length == 1) itemTypeMapping = mapping.Elements[0].Mapping; else itemTypeMapping = null; if (itemTypeMapping is EnumMapping) { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } else if (itemTypeMapping is PrimitiveMapping) { itemTypeNamespace = itemTypeMapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace; itemTypeName = itemTypeMapping.TypeDesc.DataType.Name; useDefaultNs = true; } else if (itemTypeMapping is StructMapping) { if (itemTypeMapping.TypeDesc.IsRoot) { itemTypeNamespace = XmlSchema.Namespace; itemTypeName = Soap.UrType; useDefaultNs = true; } else { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } } else if (itemTypeMapping is ArrayMapping) { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } else { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSoapArray, mapping.TypeDesc.FullName)); } itemTypeName = CodeIdentifier.MakePascal(itemTypeName); string uniqueName = "ArrayOf" + itemTypeName; string ns = useDefaultNs ? defaultNs : itemTypeNamespace; int i = 1; TypeMapping existingMapping = (TypeMapping)types[uniqueName, ns]; while (existingMapping != null) { if (existingMapping is ArrayMapping) { ArrayMapping arrayMapping = (ArrayMapping)existingMapping; if (AccessorMapping.ElementsMatch(arrayMapping.Elements, mapping.Elements)) { break; } } // need to re-name the mapping uniqueName = itemTypeName + i.ToString(CultureInfo.InvariantCulture); existingMapping = (TypeMapping)types[uniqueName, ns]; i++; } mapping.Namespace = ns; mapping.TypeName = uniqueName; } PrimitiveMapping ImportPrimitiveMapping(PrimitiveModel model, string dataType) { PrimitiveMapping mapping = new PrimitiveMapping(); mapping.IsSoap = true; if (dataType.Length > 0) { mapping.TypeDesc = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); if (mapping.TypeDesc == null) { // try it as a non-Xsd type mapping.TypeDesc = typeScope.GetTypeDesc(dataType, UrtTypes.Namespace); if (mapping.TypeDesc == null) { throw new InvalidOperationException(Res.GetString(Res.XmlUdeclaredXsdType, dataType)); } } } else { mapping.TypeDesc = model.TypeDesc; } mapping.TypeName = mapping.TypeDesc.DataType.Name; mapping.Namespace = mapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace; return mapping; } EnumMapping ImportEnumMapping(EnumModel model) { SoapAttributes a = GetAttributes(model.Type); string typeNs = defaultNs; if (a.SoapType != null && a.SoapType.Namespace != null) typeNs = a.SoapType.Namespace; string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name); typeName = XmlConvert.EncodeLocalName(typeName); EnumMapping mapping = (EnumMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc); if (mapping == null) { mapping = new EnumMapping(); mapping.IsSoap = true; mapping.TypeDesc = model.TypeDesc; mapping.TypeName = typeName; mapping.Namespace = typeNs; mapping.IsFlags = model.Type.IsDefined(typeof(FlagsAttribute), false); typeScope.AddTypeMapping(mapping); types.Add(typeName, typeNs, mapping); ArrayList constants = new ArrayList(); for (int i = 0; i < model.Constants.Length; i++) { ConstantMapping constant = ImportConstantMapping(model.Constants[i]); if (constant != null) constants.Add(constant); } if (constants.Count == 0) { throw new InvalidOperationException(Res.GetString(Res.XmlNoSerializableMembers, model.TypeDesc.FullName)); } mapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping)); } return mapping; } ConstantMapping ImportConstantMapping(ConstantModel model) { SoapAttributes a = GetAttributes(model.FieldInfo); if (a.SoapIgnore) return null; if ((a.SoapFlags & ~SoapAttributeFlags.Enum) != 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEnumAttribute)); if (a.SoapEnum == null) a.SoapEnum = new SoapEnumAttribute(); ConstantMapping constant = new ConstantMapping(); constant.XmlName = a.SoapEnum.Name.Length == 0 ? model.Name : a.SoapEnum.Name; constant.Name = model.Name; constant.Value = model.Value; return constant; } MembersMapping ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, string ns, bool hasWrapperElement, bool writeAccessors, bool validateWrapperElement, RecursionLimiter limiter) { MembersMapping members = new MembersMapping(); members.TypeDesc = typeScope.GetTypeDesc(typeof(object[])); MemberMapping[] mappings = new MemberMapping[xmlReflectionMembers.Length]; for (int i = 0; i < mappings.Length; i++) { try { XmlReflectionMember member = xmlReflectionMembers[i]; MemberMapping mapping = ImportMemberMapping(member, ns, xmlReflectionMembers, hasWrapperElement ? XmlSchemaForm.Unqualified : XmlSchemaForm.Qualified, limiter); if (member.IsReturnValue && writeAccessors) { // no special treatment for return values with doc/enc if (i > 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidReturnPosition)); mapping.IsReturnValue = true; } mappings[i] = mapping; } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } throw ReflectionException(xmlReflectionMembers[i].MemberName, e); } } members.Members = mappings; members.HasWrapperElement = hasWrapperElement; if (hasWrapperElement) { members.ValidateRpcWrapperElement = validateWrapperElement; } members.WriteAccessors = writeAccessors; members.IsSoap = true; if (hasWrapperElement && !writeAccessors) members.Namespace = ns; return members; } MemberMapping ImportMemberMapping(XmlReflectionMember xmlReflectionMember, string ns, XmlReflectionMember[] xmlReflectionMembers, XmlSchemaForm form, RecursionLimiter limiter) { SoapAttributes a = xmlReflectionMember.SoapAttributes; if (a.SoapIgnore) return null; MemberMapping member = new MemberMapping(); member.IsSoap = true; member.Name = xmlReflectionMember.MemberName; bool checkSpecified = XmlReflectionImporter.FindSpecifiedMember(xmlReflectionMember.MemberName, xmlReflectionMembers) != null; FieldModel model = new FieldModel(xmlReflectionMember.MemberName, xmlReflectionMember.MemberType, typeScope.GetTypeDesc(xmlReflectionMember.MemberType), checkSpecified, false); member.CheckShouldPersist = model.CheckShouldPersist; member.CheckSpecified = model.CheckSpecified; member.ReadOnly = model.ReadOnly; // || !model.FieldTypeDesc.HasDefaultConstructor; ImportAccessorMapping(member, model, a, ns, form, limiter); if (xmlReflectionMember.OverrideIsNullable) member.Elements[0].IsNullable = false; return member; } MemberMapping ImportFieldMapping(FieldModel model, SoapAttributes a, string ns, RecursionLimiter limiter) { if (a.SoapIgnore) return null; MemberMapping member = new MemberMapping(); member.IsSoap = true; member.Name = model.Name; member.CheckShouldPersist = model.CheckShouldPersist; member.CheckSpecified = model.CheckSpecified; member.ReadOnly = model.ReadOnly; // || !model.FieldTypeDesc.HasDefaultConstructor; ImportAccessorMapping(member, model, a, ns, XmlSchemaForm.Unqualified, limiter); return member; } void ImportAccessorMapping(MemberMapping accessor, FieldModel model, SoapAttributes a, string ns, XmlSchemaForm form, RecursionLimiter limiter) { Type accessorType = model.FieldType; string accessorName = model.Name; accessor.TypeDesc = typeScope.GetTypeDesc(accessorType); if (accessor.TypeDesc.IsVoid) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidVoid)); } SoapAttributeFlags flags = a.SoapFlags; if ((flags & SoapAttributeFlags.Attribute) == SoapAttributeFlags.Attribute) { if (!accessor.TypeDesc.IsPrimitive && !accessor.TypeDesc.IsEnum) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalSoapAttribute, accessorName, accessor.TypeDesc.FullName)); if ((flags & SoapAttributeFlags.Attribute) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidElementAttribute)); AttributeAccessor attribute = new AttributeAccessor(); attribute.Name = Accessor.EscapeQName(a.SoapAttribute == null || a.SoapAttribute.AttributeName.Length == 0 ? accessorName : a.SoapAttribute.AttributeName); attribute.Namespace = a.SoapAttribute == null || a.SoapAttribute.Namespace == null ? ns : a.SoapAttribute.Namespace; attribute.Form = XmlSchemaForm.Qualified; // attributes are always qualified since they're only used for encoded soap headers attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), (a.SoapAttribute == null ? String.Empty : a.SoapAttribute.DataType), limiter); attribute.Default = GetDefaultValue(model.FieldTypeDesc, a); accessor.Attribute = attribute; accessor.Elements = new ElementAccessor[0]; } else { if ((flags & SoapAttributeFlags.Element) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidElementAttribute)); ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = XmlConvert.EncodeLocalName(a.SoapElement == null || a.SoapElement.ElementName.Length == 0 ? accessorName : a.SoapElement.ElementName); element.Namespace = ns; element.Form = form; element.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), (a.SoapElement == null ? String.Empty : a.SoapElement.DataType), limiter); if (a.SoapElement != null) element.IsNullable = a.SoapElement.IsNullable; accessor.Elements = new ElementAccessor[] { element }; } } static ElementAccessor CreateElementAccessor(TypeMapping mapping, string ns) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = mapping.TypeName; //XmlConvert.EncodeLocalName(name == null || name.Length == 0 ? mapping.TypeName : name); element.Namespace = ns; element.Mapping = mapping; return element; } object GetDefaultValue(TypeDesc fieldTypeDesc, SoapAttributes a) { if (a.SoapDefaultValue == null || a.SoapDefaultValue == DBNull.Value) return null; if (!(fieldTypeDesc.Kind == TypeKind.Primitive || fieldTypeDesc.Kind == TypeKind.Enum)) { a.SoapDefaultValue = null; return a.SoapDefaultValue; } // for enums validate and return a string representation if (fieldTypeDesc.Kind == TypeKind.Enum) { if (fieldTypeDesc != typeScope.GetTypeDesc(a.SoapDefaultValue.GetType())) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultEnumValue, a.SoapDefaultValue.GetType().FullName, fieldTypeDesc.FullName)); string strValue = Enum.Format(a.SoapDefaultValue.GetType(), a.SoapDefaultValue, "G").Replace(",", " "); string numValue = Enum.Format(a.SoapDefaultValue.GetType(), a.SoapDefaultValue, "D"); if (strValue == numValue) // means enum value wasn't recognized throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultValue, strValue, a.SoapDefaultValue.GetType().FullName)); return strValue; } return a.SoapDefaultValue; } internal string XsdTypeName(Type type) { if (type == typeof(object)) return Soap.UrType; TypeDesc typeDesc = typeScope.GetTypeDesc(type); if (typeDesc.IsPrimitive && typeDesc.DataType != null && typeDesc.DataType.Name != null && typeDesc.DataType.Name.Length > 0) return typeDesc.DataType.Name; return XsdTypeName(type, GetAttributes(type), typeDesc.Name); } internal string XsdTypeName(Type type, SoapAttributes a, string name) { string typeName = name; if (a.SoapType != null && a.SoapType.TypeName.Length > 0) typeName = a.SoapType.TypeName; if (type.IsGenericType && typeName.IndexOf('{') >= 0) { Type genType = type.GetGenericTypeDefinition(); Type[] names = genType.GetGenericArguments(); Type[] types = type.GetGenericArguments(); for (int i = 0; i < names.Length; i++) { string argument = "{" + names[i] + "}"; if (typeName.Contains(argument)) { typeName = typeName.Replace(argument, XsdTypeName(types[i])); if (typeName.IndexOf('{') < 0) { break; } } } } // return typeName; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //[To be supplied.] ///// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace System.Xml.Serialization { using System.Reflection; using System; using System.Globalization; using System.Xml.Schema; using System.Collections; using System.ComponentModel; using System.Threading; ////// /// public class SoapReflectionImporter { TypeScope typeScope; SoapAttributeOverrides attributeOverrides; NameTable types = new NameTable(); // xmltypename + xmlns -> Mapping NameTable nullables = new NameTable(); // xmltypename + xmlns -> NullableMapping StructMapping root; string defaultNs; ModelScope modelScope; ///[To be supplied.] ////// /// public SoapReflectionImporter() : this(null, null) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(string defaultNamespace) : this(null, defaultNamespace) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(SoapAttributeOverrides attributeOverrides) : this(attributeOverrides, null) { } ///[To be supplied.] ////// /// public SoapReflectionImporter(SoapAttributeOverrides attributeOverrides, string defaultNamespace) { if (defaultNamespace == null) defaultNamespace = String.Empty; if (attributeOverrides == null) attributeOverrides = new SoapAttributeOverrides(); this.attributeOverrides = attributeOverrides; this.defaultNs = defaultNamespace; this.typeScope = new TypeScope(); this.modelScope = new ModelScope(this.typeScope); } ///[To be supplied.] ////// /// public void IncludeTypes(ICustomAttributeProvider provider) { IncludeTypes(provider, new RecursionLimiter()); } void IncludeTypes(ICustomAttributeProvider provider, RecursionLimiter limiter) { object[] attrs = provider.GetCustomAttributes(typeof(SoapIncludeAttribute), false); for (int i = 0; i < attrs.Length; i++) { IncludeType(((SoapIncludeAttribute)attrs[i]).Type, limiter); } } ///[To be supplied.] ////// /// public void IncludeType(Type type) { IncludeType(type, new RecursionLimiter()); } void IncludeType(Type type, RecursionLimiter limiter) { ImportTypeMapping(modelScope.GetTypeModel(type), limiter); } ///[To be supplied.] ////// /// public XmlTypeMapping ImportTypeMapping(Type type) { return ImportTypeMapping(type, null); } ///[To be supplied.] ////// /// public XmlTypeMapping ImportTypeMapping(Type type, string defaultNamespace) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Mapping = ImportTypeMapping(modelScope.GetTypeModel(type), new RecursionLimiter()); element.Name = element.Mapping.DefaultElementName; element.Namespace = element.Mapping.Namespace == null ? defaultNamespace : element.Mapping.Namespace; element.Form = XmlSchemaForm.Qualified; XmlTypeMapping xmlMapping = new XmlTypeMapping(typeScope, element); xmlMapping.SetKeyInternal(XmlMapping.GenerateKey(type, null, defaultNamespace)); xmlMapping.IsSoap = true; xmlMapping.GenerateSerializer = true; return xmlMapping; } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members) { return ImportMembersMapping(elementName, ns, members, true, true, false); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors) { return ImportMembersMapping(elementName, ns, members, hasWrapperElement, writeAccessors, false); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate) { return ImportMembersMapping(elementName, ns, members, hasWrapperElement, writeAccessors, validate, XmlMappingAccess.Read | XmlMappingAccess.Write); } ///[To be supplied.] ////// /// public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate, XmlMappingAccess access) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = elementName == null || elementName.Length == 0 ? elementName : XmlConvert.EncodeLocalName(elementName); element.Mapping = ImportMembersMapping(members, ns, hasWrapperElement, writeAccessors, validate, new RecursionLimiter()); element.Mapping.TypeName = elementName; element.Namespace = element.Mapping.Namespace == null ? ns : element.Mapping.Namespace; element.Form = XmlSchemaForm.Qualified; XmlMembersMapping xmlMapping = new XmlMembersMapping(typeScope, element, access); xmlMapping.IsSoap = true; xmlMapping.GenerateSerializer = true; return xmlMapping; } Exception ReflectionException(string context, Exception e) { return new InvalidOperationException(Res.GetString(Res.XmlReflectionError, context), e); } SoapAttributes GetAttributes(Type type) { SoapAttributes attrs = attributeOverrides[type]; if (attrs != null) return attrs; return new SoapAttributes(type); } SoapAttributes GetAttributes(MemberInfo memberInfo) { SoapAttributes attrs = attributeOverrides[memberInfo.DeclaringType, memberInfo.Name]; if (attrs != null) return attrs; return new SoapAttributes(memberInfo); } TypeMapping ImportTypeMapping(TypeModel model, RecursionLimiter limiter) { return ImportTypeMapping(model, String.Empty, limiter); } TypeMapping ImportTypeMapping(TypeModel model, string dataType, RecursionLimiter limiter) { if (dataType.Length > 0) { if (!model.TypeDesc.IsPrimitive) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDataTypeUsage, dataType, "SoapElementAttribute.DataType")); } TypeDesc td = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); if (td == null) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidXsdDataType, dataType, "SoapElementAttribute.DataType", new XmlQualifiedName(dataType, XmlSchema.Namespace).ToString())); } if (model.TypeDesc.FullName != td.FullName) { throw new InvalidOperationException(Res.GetString(Res.XmlDataTypeMismatch, dataType, "SoapElementAttribute.DataType", model.TypeDesc.FullName)); } } SoapAttributes a = GetAttributes(model.Type); if ((a.SoapFlags & ~SoapAttributeFlags.Type) != 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidTypeAttributes, model.Type.FullName)); switch (model.TypeDesc.Kind) { case TypeKind.Enum: return ImportEnumMapping((EnumModel)model); case TypeKind.Primitive: return ImportPrimitiveMapping((PrimitiveModel)model, dataType); case TypeKind.Array: case TypeKind.Collection: case TypeKind.Enumerable: return ImportArrayLikeMapping((ArrayModel)model, limiter); case TypeKind.Root: case TypeKind.Class: case TypeKind.Struct: if (model.TypeDesc.IsOptionalValue) { TypeDesc baseTypeDesc = model.TypeDesc.BaseTypeDesc; SoapAttributes baseAttributes = GetAttributes(baseTypeDesc.Type); string typeNs = defaultNs; if (baseAttributes.SoapType != null && baseAttributes.SoapType.Namespace != null) typeNs = baseAttributes.SoapType.Namespace; TypeDesc valueTypeDesc = string.IsNullOrEmpty(dataType) ? model.TypeDesc.BaseTypeDesc : typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); string xsdTypeName = string.IsNullOrEmpty(dataType) ? model.TypeDesc.BaseTypeDesc.Name : dataType; TypeMapping baseMapping = GetTypeMapping(xsdTypeName, typeNs, valueTypeDesc); if (baseMapping == null) baseMapping = ImportTypeMapping(modelScope.GetTypeModel(baseTypeDesc.Type), dataType, limiter); return CreateNullableMapping(baseMapping, model.TypeDesc.Type); } else { return ImportStructLikeMapping((StructModel)model, limiter); } default: throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedSoapTypeKind, model.TypeDesc.FullName)); } } StructMapping CreateRootMapping() { TypeDesc typeDesc = typeScope.GetTypeDesc(typeof(object)); StructMapping mapping = new StructMapping(); mapping.IsSoap = true; mapping.TypeDesc = typeDesc; mapping.Members = new MemberMapping[0]; mapping.IncludeInSchema = false; mapping.TypeName = Soap.UrType; mapping.Namespace = XmlSchema.Namespace; return mapping; } StructMapping GetRootMapping() { if (root == null) { root = CreateRootMapping(); typeScope.AddTypeMapping(root); } return root; } TypeMapping GetTypeMapping(string typeName, string ns, TypeDesc typeDesc) { TypeMapping mapping = (TypeMapping)types[typeName, ns]; if (mapping == null) return null; if (mapping.TypeDesc != typeDesc) throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, mapping.TypeDesc.FullName, typeName, ns)); return mapping; } NullableMapping CreateNullableMapping(TypeMapping baseMapping, Type type) { TypeDesc typeDesc = baseMapping.TypeDesc.GetNullableTypeDesc(type); TypeMapping existingMapping = (TypeMapping)nullables[baseMapping.TypeName, baseMapping.Namespace]; NullableMapping mapping; if (existingMapping != null) { if (existingMapping is NullableMapping) { mapping = (NullableMapping)existingMapping; if (mapping.BaseMapping is PrimitiveMapping && baseMapping is PrimitiveMapping) return mapping; else if (mapping.BaseMapping == baseMapping) { return mapping; } else { throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace)); } } else if (!(baseMapping is PrimitiveMapping)){ throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace)); } } mapping = new NullableMapping(); mapping.BaseMapping = baseMapping; mapping.TypeDesc = typeDesc; mapping.TypeName = baseMapping.TypeName; mapping.Namespace = baseMapping.Namespace; mapping.IncludeInSchema = false; //baseMapping.IncludeInSchema; nullables.Add(baseMapping.TypeName, mapping.Namespace, mapping); typeScope.AddTypeMapping(mapping); return mapping; } StructMapping ImportStructLikeMapping(StructModel model, RecursionLimiter limiter) { if (model.TypeDesc.Kind == TypeKind.Root) return GetRootMapping(); SoapAttributes a = GetAttributes(model.Type); string typeNs = defaultNs; if (a.SoapType != null && a.SoapType.Namespace != null) typeNs = a.SoapType.Namespace; string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name); typeName = XmlConvert.EncodeLocalName(typeName); StructMapping mapping = (StructMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc); if (mapping == null) { mapping = new StructMapping(); mapping.IsSoap = true; mapping.TypeDesc = model.TypeDesc; mapping.Namespace = typeNs; mapping.TypeName = typeName; if (a.SoapType != null) mapping.IncludeInSchema = a.SoapType.IncludeInSchema; typeScope.AddTypeMapping(mapping); types.Add(typeName, typeNs, mapping); if (limiter.IsExceededLimit) { limiter.DeferredWorkItems.Add(new ImportStructWorkItem(model, mapping)); return mapping; } limiter.Depth++; InitializeStructMembers(mapping, model, limiter); while (limiter.DeferredWorkItems.Count > 0) { int index = limiter.DeferredWorkItems.Count - 1; ImportStructWorkItem item = limiter.DeferredWorkItems[index]; if (InitializeStructMembers(item.Mapping, item.Model, limiter)) { // // if InitializeStructMembers returns true, then there were *no* chages to the DeferredWorkItems // #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (index != limiter.DeferredWorkItems.Count - 1) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "DeferredWorkItems.Count have changed")); if (item != limiter.DeferredWorkItems[index]) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "DeferredWorkItems.Top have changed")); #endif // Remove the last work item limiter.DeferredWorkItems.RemoveAt(index); } } limiter.Depth--; } return mapping; } bool InitializeStructMembers(StructMapping mapping, StructModel model, RecursionLimiter limiter) { if (mapping.IsFullyInitialized) return true; if (model.TypeDesc.BaseTypeDesc != null) { StructMapping baseMapping = ImportStructLikeMapping((StructModel)modelScope.GetTypeModel(model.Type.BaseType, false), limiter); // check to see if the import of the baseMapping was deffered int baseIndex = limiter.DeferredWorkItems.IndexOf(mapping.BaseMapping); if (baseIndex < 0) { mapping.BaseMapping = baseMapping; } else { // the import of the baseMapping was deffered, make sure that the derived mappings is deffered as well if (!limiter.DeferredWorkItems.Contains(mapping)) { limiter.DeferredWorkItems.Add(new ImportStructWorkItem(model, mapping)); } // make sure that baseMapping get processed before the derived int top = limiter.DeferredWorkItems.Count-1; if (baseIndex < top) { ImportStructWorkItem baseMappingWorkItem = limiter.DeferredWorkItems[baseIndex]; limiter.DeferredWorkItems[baseIndex] = limiter.DeferredWorkItems[top]; limiter.DeferredWorkItems[top] = baseMappingWorkItem; } return false; } } ArrayList members = new ArrayList(); foreach (MemberInfo memberInfo in model.GetMemberInfos()) { if ((memberInfo.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0) continue; SoapAttributes memberAttrs = GetAttributes(memberInfo); if (memberAttrs.SoapIgnore) continue; FieldModel fieldModel = model.GetFieldModel(memberInfo); if (fieldModel == null) continue; MemberMapping member = ImportFieldMapping(fieldModel, memberAttrs, mapping.Namespace, limiter); if (member == null) continue; if (!member.TypeDesc.IsPrimitive && !member.TypeDesc.IsEnum && !member.TypeDesc.IsOptionalValue) { if (model.TypeDesc.IsValueType) throw new NotSupportedException(Res.GetString(Res.XmlRpcRefsInValueType, model.TypeDesc.FullName)); if (member.TypeDesc.IsValueType) throw new NotSupportedException(Res.GetString(Res.XmlRpcNestedValueType, member.TypeDesc.FullName)); } if (mapping.BaseMapping != null) { if (mapping.BaseMapping.Declares(member, mapping.TypeName)) continue; } members.Add(member); } mapping.Members = (MemberMapping[])members.ToArray(typeof(MemberMapping)); if (mapping.BaseMapping == null) mapping.BaseMapping = GetRootMapping(); IncludeTypes(model.Type, limiter); return true; } ArrayMapping ImportArrayLikeMapping(ArrayModel model, RecursionLimiter limiter) { ArrayMapping mapping = new ArrayMapping(); mapping.IsSoap = true; TypeMapping itemTypeMapping = ImportTypeMapping(model.Element, limiter); if (itemTypeMapping.TypeDesc.IsValueType && !itemTypeMapping.TypeDesc.IsPrimitive && !itemTypeMapping.TypeDesc.IsEnum) throw new NotSupportedException(Res.GetString(Res.XmlRpcArrayOfValueTypes, model.TypeDesc.FullName)); mapping.TypeDesc = model.TypeDesc; mapping.Elements = new ElementAccessor[] { CreateElementAccessor(itemTypeMapping, mapping.Namespace) }; SetArrayMappingType(mapping); // in the case of an ArrayMapping we can have more that one mapping correspond to a type // examples of that are ArrayList and object[] both will map tp ArrayOfur-type // so we create a link list for all mappings of the same XSD type ArrayMapping existingMapping = (ArrayMapping)types[mapping.TypeName, mapping.Namespace]; if (existingMapping != null) { ArrayMapping first = existingMapping; while (existingMapping != null) { if (existingMapping.TypeDesc == model.TypeDesc) return existingMapping; existingMapping = existingMapping.Next; } mapping.Next = first; types[mapping.TypeName, mapping.Namespace] = mapping; return mapping; } typeScope.AddTypeMapping(mapping); types.Add(mapping.TypeName, mapping.Namespace, mapping); IncludeTypes(model.Type); return mapping; } // void SetArrayMappingType(ArrayMapping mapping) { bool useDefaultNs = false; string itemTypeName; string itemTypeNamespace; TypeMapping itemTypeMapping; if (mapping.Elements.Length == 1) itemTypeMapping = mapping.Elements[0].Mapping; else itemTypeMapping = null; if (itemTypeMapping is EnumMapping) { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } else if (itemTypeMapping is PrimitiveMapping) { itemTypeNamespace = itemTypeMapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace; itemTypeName = itemTypeMapping.TypeDesc.DataType.Name; useDefaultNs = true; } else if (itemTypeMapping is StructMapping) { if (itemTypeMapping.TypeDesc.IsRoot) { itemTypeNamespace = XmlSchema.Namespace; itemTypeName = Soap.UrType; useDefaultNs = true; } else { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } } else if (itemTypeMapping is ArrayMapping) { itemTypeNamespace = itemTypeMapping.Namespace; itemTypeName = itemTypeMapping.TypeName; } else { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSoapArray, mapping.TypeDesc.FullName)); } itemTypeName = CodeIdentifier.MakePascal(itemTypeName); string uniqueName = "ArrayOf" + itemTypeName; string ns = useDefaultNs ? defaultNs : itemTypeNamespace; int i = 1; TypeMapping existingMapping = (TypeMapping)types[uniqueName, ns]; while (existingMapping != null) { if (existingMapping is ArrayMapping) { ArrayMapping arrayMapping = (ArrayMapping)existingMapping; if (AccessorMapping.ElementsMatch(arrayMapping.Elements, mapping.Elements)) { break; } } // need to re-name the mapping uniqueName = itemTypeName + i.ToString(CultureInfo.InvariantCulture); existingMapping = (TypeMapping)types[uniqueName, ns]; i++; } mapping.Namespace = ns; mapping.TypeName = uniqueName; } PrimitiveMapping ImportPrimitiveMapping(PrimitiveModel model, string dataType) { PrimitiveMapping mapping = new PrimitiveMapping(); mapping.IsSoap = true; if (dataType.Length > 0) { mapping.TypeDesc = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace); if (mapping.TypeDesc == null) { // try it as a non-Xsd type mapping.TypeDesc = typeScope.GetTypeDesc(dataType, UrtTypes.Namespace); if (mapping.TypeDesc == null) { throw new InvalidOperationException(Res.GetString(Res.XmlUdeclaredXsdType, dataType)); } } } else { mapping.TypeDesc = model.TypeDesc; } mapping.TypeName = mapping.TypeDesc.DataType.Name; mapping.Namespace = mapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace; return mapping; } EnumMapping ImportEnumMapping(EnumModel model) { SoapAttributes a = GetAttributes(model.Type); string typeNs = defaultNs; if (a.SoapType != null && a.SoapType.Namespace != null) typeNs = a.SoapType.Namespace; string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name); typeName = XmlConvert.EncodeLocalName(typeName); EnumMapping mapping = (EnumMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc); if (mapping == null) { mapping = new EnumMapping(); mapping.IsSoap = true; mapping.TypeDesc = model.TypeDesc; mapping.TypeName = typeName; mapping.Namespace = typeNs; mapping.IsFlags = model.Type.IsDefined(typeof(FlagsAttribute), false); typeScope.AddTypeMapping(mapping); types.Add(typeName, typeNs, mapping); ArrayList constants = new ArrayList(); for (int i = 0; i < model.Constants.Length; i++) { ConstantMapping constant = ImportConstantMapping(model.Constants[i]); if (constant != null) constants.Add(constant); } if (constants.Count == 0) { throw new InvalidOperationException(Res.GetString(Res.XmlNoSerializableMembers, model.TypeDesc.FullName)); } mapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping)); } return mapping; } ConstantMapping ImportConstantMapping(ConstantModel model) { SoapAttributes a = GetAttributes(model.FieldInfo); if (a.SoapIgnore) return null; if ((a.SoapFlags & ~SoapAttributeFlags.Enum) != 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEnumAttribute)); if (a.SoapEnum == null) a.SoapEnum = new SoapEnumAttribute(); ConstantMapping constant = new ConstantMapping(); constant.XmlName = a.SoapEnum.Name.Length == 0 ? model.Name : a.SoapEnum.Name; constant.Name = model.Name; constant.Value = model.Value; return constant; } MembersMapping ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, string ns, bool hasWrapperElement, bool writeAccessors, bool validateWrapperElement, RecursionLimiter limiter) { MembersMapping members = new MembersMapping(); members.TypeDesc = typeScope.GetTypeDesc(typeof(object[])); MemberMapping[] mappings = new MemberMapping[xmlReflectionMembers.Length]; for (int i = 0; i < mappings.Length; i++) { try { XmlReflectionMember member = xmlReflectionMembers[i]; MemberMapping mapping = ImportMemberMapping(member, ns, xmlReflectionMembers, hasWrapperElement ? XmlSchemaForm.Unqualified : XmlSchemaForm.Qualified, limiter); if (member.IsReturnValue && writeAccessors) { // no special treatment for return values with doc/enc if (i > 0) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidReturnPosition)); mapping.IsReturnValue = true; } mappings[i] = mapping; } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } throw ReflectionException(xmlReflectionMembers[i].MemberName, e); } } members.Members = mappings; members.HasWrapperElement = hasWrapperElement; if (hasWrapperElement) { members.ValidateRpcWrapperElement = validateWrapperElement; } members.WriteAccessors = writeAccessors; members.IsSoap = true; if (hasWrapperElement && !writeAccessors) members.Namespace = ns; return members; } MemberMapping ImportMemberMapping(XmlReflectionMember xmlReflectionMember, string ns, XmlReflectionMember[] xmlReflectionMembers, XmlSchemaForm form, RecursionLimiter limiter) { SoapAttributes a = xmlReflectionMember.SoapAttributes; if (a.SoapIgnore) return null; MemberMapping member = new MemberMapping(); member.IsSoap = true; member.Name = xmlReflectionMember.MemberName; bool checkSpecified = XmlReflectionImporter.FindSpecifiedMember(xmlReflectionMember.MemberName, xmlReflectionMembers) != null; FieldModel model = new FieldModel(xmlReflectionMember.MemberName, xmlReflectionMember.MemberType, typeScope.GetTypeDesc(xmlReflectionMember.MemberType), checkSpecified, false); member.CheckShouldPersist = model.CheckShouldPersist; member.CheckSpecified = model.CheckSpecified; member.ReadOnly = model.ReadOnly; // || !model.FieldTypeDesc.HasDefaultConstructor; ImportAccessorMapping(member, model, a, ns, form, limiter); if (xmlReflectionMember.OverrideIsNullable) member.Elements[0].IsNullable = false; return member; } MemberMapping ImportFieldMapping(FieldModel model, SoapAttributes a, string ns, RecursionLimiter limiter) { if (a.SoapIgnore) return null; MemberMapping member = new MemberMapping(); member.IsSoap = true; member.Name = model.Name; member.CheckShouldPersist = model.CheckShouldPersist; member.CheckSpecified = model.CheckSpecified; member.ReadOnly = model.ReadOnly; // || !model.FieldTypeDesc.HasDefaultConstructor; ImportAccessorMapping(member, model, a, ns, XmlSchemaForm.Unqualified, limiter); return member; } void ImportAccessorMapping(MemberMapping accessor, FieldModel model, SoapAttributes a, string ns, XmlSchemaForm form, RecursionLimiter limiter) { Type accessorType = model.FieldType; string accessorName = model.Name; accessor.TypeDesc = typeScope.GetTypeDesc(accessorType); if (accessor.TypeDesc.IsVoid) { throw new InvalidOperationException(Res.GetString(Res.XmlInvalidVoid)); } SoapAttributeFlags flags = a.SoapFlags; if ((flags & SoapAttributeFlags.Attribute) == SoapAttributeFlags.Attribute) { if (!accessor.TypeDesc.IsPrimitive && !accessor.TypeDesc.IsEnum) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalSoapAttribute, accessorName, accessor.TypeDesc.FullName)); if ((flags & SoapAttributeFlags.Attribute) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidElementAttribute)); AttributeAccessor attribute = new AttributeAccessor(); attribute.Name = Accessor.EscapeQName(a.SoapAttribute == null || a.SoapAttribute.AttributeName.Length == 0 ? accessorName : a.SoapAttribute.AttributeName); attribute.Namespace = a.SoapAttribute == null || a.SoapAttribute.Namespace == null ? ns : a.SoapAttribute.Namespace; attribute.Form = XmlSchemaForm.Qualified; // attributes are always qualified since they're only used for encoded soap headers attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), (a.SoapAttribute == null ? String.Empty : a.SoapAttribute.DataType), limiter); attribute.Default = GetDefaultValue(model.FieldTypeDesc, a); accessor.Attribute = attribute; accessor.Elements = new ElementAccessor[0]; } else { if ((flags & SoapAttributeFlags.Element) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidElementAttribute)); ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = XmlConvert.EncodeLocalName(a.SoapElement == null || a.SoapElement.ElementName.Length == 0 ? accessorName : a.SoapElement.ElementName); element.Namespace = ns; element.Form = form; element.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), (a.SoapElement == null ? String.Empty : a.SoapElement.DataType), limiter); if (a.SoapElement != null) element.IsNullable = a.SoapElement.IsNullable; accessor.Elements = new ElementAccessor[] { element }; } } static ElementAccessor CreateElementAccessor(TypeMapping mapping, string ns) { ElementAccessor element = new ElementAccessor(); element.IsSoap = true; element.Name = mapping.TypeName; //XmlConvert.EncodeLocalName(name == null || name.Length == 0 ? mapping.TypeName : name); element.Namespace = ns; element.Mapping = mapping; return element; } object GetDefaultValue(TypeDesc fieldTypeDesc, SoapAttributes a) { if (a.SoapDefaultValue == null || a.SoapDefaultValue == DBNull.Value) return null; if (!(fieldTypeDesc.Kind == TypeKind.Primitive || fieldTypeDesc.Kind == TypeKind.Enum)) { a.SoapDefaultValue = null; return a.SoapDefaultValue; } // for enums validate and return a string representation if (fieldTypeDesc.Kind == TypeKind.Enum) { if (fieldTypeDesc != typeScope.GetTypeDesc(a.SoapDefaultValue.GetType())) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultEnumValue, a.SoapDefaultValue.GetType().FullName, fieldTypeDesc.FullName)); string strValue = Enum.Format(a.SoapDefaultValue.GetType(), a.SoapDefaultValue, "G").Replace(",", " "); string numValue = Enum.Format(a.SoapDefaultValue.GetType(), a.SoapDefaultValue, "D"); if (strValue == numValue) // means enum value wasn't recognized throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultValue, strValue, a.SoapDefaultValue.GetType().FullName)); return strValue; } return a.SoapDefaultValue; } internal string XsdTypeName(Type type) { if (type == typeof(object)) return Soap.UrType; TypeDesc typeDesc = typeScope.GetTypeDesc(type); if (typeDesc.IsPrimitive && typeDesc.DataType != null && typeDesc.DataType.Name != null && typeDesc.DataType.Name.Length > 0) return typeDesc.DataType.Name; return XsdTypeName(type, GetAttributes(type), typeDesc.Name); } internal string XsdTypeName(Type type, SoapAttributes a, string name) { string typeName = name; if (a.SoapType != null && a.SoapType.TypeName.Length > 0) typeName = a.SoapType.TypeName; if (type.IsGenericType && typeName.IndexOf('{') >= 0) { Type genType = type.GetGenericTypeDefinition(); Type[] names = genType.GetGenericArguments(); Type[] types = type.GetGenericArguments(); for (int i = 0; i < names.Length; i++) { string argument = "{" + names[i] + "}"; if (typeName.Contains(argument)) { typeName = typeName.Replace(argument, XsdTypeName(types[i])); if (typeName.IndexOf('{') < 0) { break; } } } } // return typeName; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.[To be supplied.] ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TailCallAnalyzer.cs
- ClassValidator.cs
- ZipIORawDataFileBlock.cs
- SerializationInfoEnumerator.cs
- HttpRuntimeSection.cs
- HostingEnvironmentSection.cs
- WebPartDisplayModeCollection.cs
- PeerObject.cs
- InkCanvas.cs
- UrlPath.cs
- PropertyHelper.cs
- AsymmetricAlgorithm.cs
- EnumBuilder.cs
- DataGridLinkButton.cs
- FixedSOMContainer.cs
- Decoder.cs
- ImportOptions.cs
- CodeTypeDelegate.cs
- ConfigurationElementProperty.cs
- ShaderEffect.cs
- DataServiceRequestArgs.cs
- LinkGrep.cs
- TypedDataSetSchemaImporterExtension.cs
- Overlapped.cs
- Exceptions.cs
- ADConnectionHelper.cs
- MatrixConverter.cs
- IOException.cs
- WindowShowOrOpenTracker.cs
- XmlSchema.cs
- WebScriptEndpointElement.cs
- ControlUtil.cs
- StringFreezingAttribute.cs
- Logging.cs
- WmlPageAdapter.cs
- ReadOnlyNameValueCollection.cs
- UnitControl.cs
- RenderingEventArgs.cs
- BordersPage.cs
- MediaSystem.cs
- SqlDataSourceConfigureSortForm.cs
- DataRelationPropertyDescriptor.cs
- XmlQueryStaticData.cs
- CodeValidator.cs
- ManagementBaseObject.cs
- FramingFormat.cs
- TreeViewCancelEvent.cs
- PasswordRecoveryAutoFormat.cs
- CurrentChangedEventManager.cs
- FloaterBaseParaClient.cs
- ConstructorExpr.cs
- MultitargetUtil.cs
- ErrorHandlerModule.cs
- DataSourceControl.cs
- CheckPair.cs
- HostTimeoutsElement.cs
- WebPart.cs
- PocoPropertyAccessorStrategy.cs
- ExpressionConverter.cs
- Operator.cs
- Pkcs9Attribute.cs
- ToolStripStatusLabel.cs
- BooleanFunctions.cs
- MILUtilities.cs
- recordstate.cs
- NetworkInformationPermission.cs
- KnownTypesProvider.cs
- InvalidDataException.cs
- WindowsPen.cs
- FileDialogPermission.cs
- KeyGesture.cs
- CollectionBuilder.cs
- EntityDataSourceViewSchema.cs
- AnimatedTypeHelpers.cs
- PasswordRecovery.cs
- JournalEntryListConverter.cs
- StructuralObject.cs
- CachedTypeface.cs
- WaveHeader.cs
- ModelItemDictionary.cs
- DirectoryLocalQuery.cs
- TemplateBindingExpression.cs
- Substitution.cs
- QuaternionAnimation.cs
- WindowsSlider.cs
- printdlgexmarshaler.cs
- Light.cs
- DbModificationCommandTree.cs
- NeedSkipTokenVisitor.cs
- UnsafeNativeMethods.cs
- ToolStripGrip.cs
- XmlExtensionFunction.cs
- PropertyMetadata.cs
- InputBinder.cs
- WriteableBitmap.cs
- GeometryGroup.cs
- CodeFieldReferenceExpression.cs
- ImageCodecInfo.cs
- FileDetails.cs
- COM2TypeInfoProcessor.cs