private bool WriteDerivedTypes(StructMapping mapping, string n, string ns, object o, bool isNullable) { Type t = o.GetType(); for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) { if (t == derived.TypeDesc.Type) { WriteStructMethod(derived, n, ns, o, isNullable, needType: true); return(true); } if (WriteDerivedTypes(derived, n, ns, o, isNullable)) { return(true); } } return(false); }
internal void SetSequence() { if (TypeDesc.IsRoot) { return; } StructMapping start = this; // find first mapping that does not have the sequence set while (start.BaseMapping != null && !start.BaseMapping.IsSequence && !start.BaseMapping.TypeDesc.IsRoot) { start = start.BaseMapping; } start.IsSequence = true; for (StructMapping derived = start.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) { derived.SetSequence(); } }
private 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 deferred int baseIndex = limiter.DeferredWorkItems.IndexOf(mapping.BaseMapping); if (baseIndex < 0) { mapping.BaseMapping = baseMapping; } else { // the import of the baseMapping was deferred, make sure that the derived mappings is deferred 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 is FieldInfo) && !(memberInfo is PropertyInfo)) { 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(SR.Format(SR.XmlRpcRefsInValueType, model.TypeDesc.FullName)); } if (member.TypeDesc.IsValueType) { throw new NotSupportedException(SR.Format(SR.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); }
private 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* changes 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(SR.Format(SR.XmlInternalErrorDetails, "DeferredWorkItems.Count have changed")); } if (item != limiter.DeferredWorkItems[index]) { throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorDetails, "DeferredWorkItems.Top have changed")); } #endif // Remove the last work item limiter.DeferredWorkItems.RemoveAt(index); } } limiter.Depth--; } return(mapping); }
private void WriteStructMethod(StructMapping mapping, string n, string ns, object o, bool isNullable, bool needType, XmlMapping parentMapping = null) { if (mapping.IsSoap && mapping.TypeDesc.IsRoot) { return; } if (!mapping.IsSoap) { if (o == null) { if (isNullable) { WriteNullTagLiteral(n, ns); } return; } if (!needType && o.GetType() != mapping.TypeDesc.Type) { if (WriteDerivedTypes(mapping, n, ns, o, isNullable)) { return; } if (mapping.TypeDesc.IsRoot) { if (WriteEnumAndArrayTypes(mapping, o, n, ns, parentMapping)) { return; } WriteTypedPrimitive(n, ns, o, true); return; } throw CreateUnknownTypeException(o); } } if (!mapping.TypeDesc.IsAbstract) { if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type)) { EscapeName = false; } XmlSerializerNamespaces xmlnsSource = null; MemberMapping[] members = TypeScope.GetAllMembers(mapping); int xmlnsMember = FindXmlnsIndex(members); if (xmlnsMember >= 0) { MemberMapping member = members[xmlnsMember]; xmlnsSource = (XmlSerializerNamespaces)GetMemberValue(o, member.Name); } if (!mapping.IsSoap) { WriteStartElement(n, ns, o, false, xmlnsSource); if (!mapping.TypeDesc.IsRoot) { if (needType) { WriteXsiType(mapping.TypeName, mapping.Namespace); } } } else if (xmlnsSource != null) { WriteNamespaceDeclarations(xmlnsSource); } for (int i = 0; i < members.Length; i++) { MemberMapping m = members[i]; string memberName = m.Name; object memberValue = GetMemberValue(o, memberName); bool isSpecified = true; bool shouldPersist = true; if (m.CheckSpecified != SpecifiedAccessor.None) { string specifiedMemberName = m.Name + "Specified"; isSpecified = (bool)GetMemberValue(o, specifiedMemberName); } if (m.CheckShouldPersist) { string methodInvoke = "ShouldSerialize" + m.Name; MethodInfo method = o.GetType().GetTypeInfo().GetDeclaredMethod(methodInvoke); shouldPersist = (bool)method.Invoke(o, Array.Empty <object>()); } if (m.Attribute != null) { if (isSpecified && shouldPersist) { WriteMember(memberValue, m.Attribute, m.TypeDesc, o); } } } for (int i = 0; i < members.Length; i++) { MemberMapping m = members[i]; string memberName = m.Name; object memberValue = GetMemberValue(o, memberName); bool isSpecified = true; bool shouldPersist = true; if (m.CheckSpecified != SpecifiedAccessor.None) { string specifiedMemberName = m.Name + "Specified"; isSpecified = (bool)GetMemberValue(o, specifiedMemberName); } if (m.CheckShouldPersist) { string methodInvoke = "ShouldSerialize" + m.Name; MethodInfo method = o.GetType().GetTypeInfo().GetDeclaredMethod(methodInvoke); shouldPersist = (bool)method.Invoke(o, Array.Empty <object>()); } if (m.Xmlns != null) { continue; } bool checkShouldPersist = m.CheckShouldPersist && (m.Elements.Length > 0 || m.Text != null); if (!checkShouldPersist) { shouldPersist = true; } object choiceSource = null; if (m.ChoiceIdentifier != null) { choiceSource = GetMemberValue(o, m.ChoiceIdentifier.MemberName); } if (isSpecified && shouldPersist) { WriteMember(memberValue, choiceSource, m.ElementsSortedByDerivation, m.Text, m.ChoiceIdentifier, m.TypeDesc, true, parentMapping); } } if (!mapping.IsSoap) { WriteEndElement(o); } } }