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); }