private void AddSchemaTypeProperty(XmlDictionaryWriter writer, PropertyInfo property, TypeToBuild parentTypeToBuild) { var createListWithoutProxyType = false; var toBuild = new TypeToBuild(property.PropertyType); var arrayItem = property.GetCustomAttribute <XmlArrayItemAttribute>(); if (arrayItem != null && !string.IsNullOrWhiteSpace(arrayItem.ElementName)) { toBuild.ChildElementName = arrayItem.ElementName; } var elementItem = property.GetCustomAttribute <XmlElementAttribute>(); if (elementItem != null && !string.IsNullOrWhiteSpace(elementItem.ElementName)) { toBuild.ChildElementName = elementItem.ElementName; createListWithoutProxyType = toBuild.Type.IsEnumerableType(); } var attributeItem = property.GetCustomAttribute <XmlAttributeAttribute>(); var messageBodyMemberAttribute = property.GetCustomAttribute <MessageBodyMemberAttribute>(); if (attributeItem != null) { var name = attributeItem.AttributeName; if (string.IsNullOrWhiteSpace(name)) { name = property.Name; } AddSchemaType(writer, toBuild, name, isAttribute: true); } else if (messageBodyMemberAttribute != null) { var name = messageBodyMemberAttribute.Name; if (string.IsNullOrWhiteSpace(name)) { name = property.Name; } AddSchemaType(writer, toBuild, name, isArray: createListWithoutProxyType, isListWithoutWrapper: createListWithoutProxyType); } else { AddSchemaType(writer, toBuild, parentTypeToBuild.ChildElementName ?? property.Name, isArray: createListWithoutProxyType, isListWithoutWrapper: createListWithoutProxyType); } }
private void SetUniqueNameForDynamicType(TypeToBuild dynamicType) { if (!_requestedDynamicTypes.TryGetValue(dynamicType.TypeName, out var elementsList)) { var elementsMap = new Dictionary <string, string> { { dynamicType.ChildElementName, "" } }; _requestedDynamicTypes.Add(dynamicType.TypeName, elementsMap); return; } if (elementsList.TryGetValue(dynamicType.ChildElementName, out var assotiatedPostfix)) { dynamicType.TypeName += $"{assotiatedPostfix}"; } else { var newPostfix = $"{elementsList.Count}"; dynamicType.TypeName += $"{newPostfix}"; elementsList.Add(dynamicType.ChildElementName, newPostfix); } }
private void AddSchemaType(XmlDictionaryWriter writer, TypeToBuild toBuild, string name, bool isArray = false, string @namespace = null, bool isAttribute = false, bool isListWithoutWrapper = false) { var type = toBuild.Type; var typeInfo = type.GetTypeInfo(); if (typeInfo.IsByRef) { type = typeInfo.GetElementType(); } var typeName = type.GetSerializedTypeName(); if (writer.TryAddSchemaTypeFromXmlSchemaProviderAttribute(type, name, SoapSerializer.XmlSerializer, _xmlNamespaceManager)) { return; } var underlyingType = Nullable.GetUnderlyingType(type); //if type is a nullable non-system struct if (underlyingType?.IsValueType == true && !underlyingType.IsEnum && underlyingType.Namespace != null && underlyingType.Namespace != "System" && !underlyingType.Namespace.StartsWith("System.")) { AddSchemaType(writer, new TypeToBuild(underlyingType) { ChildElementName = toBuild.TypeName }, name, isArray, @namespace, isAttribute); return; } writer.WriteStartElement(isAttribute ? "attribute" : "element", Namespaces.XMLNS_XSD); // Check for null, since we may use empty NS if (@namespace != null) { writer.WriteAttributeString("targetNamespace", @namespace); } else if (typeInfo.IsEnum || underlyingType?.IsEnum == true || (typeInfo.IsValueType && typeInfo.Namespace != null && (typeInfo.Namespace == "System" || typeInfo.Namespace.StartsWith("System."))) || (type.Name == "String") || (type.Name == "Byte[]") ) { XmlQualifiedName xsTypename; if (typeof(DateTimeOffset).IsAssignableFrom(type)) { if (string.IsNullOrEmpty(name)) { name = typeName; } Namespaces.AddNamespaceIfNotAlreadyPresentAndGetPrefix(_xmlNamespaceManager, "nsdto", Namespaces.SYSTEM_NS); xsTypename = new XmlQualifiedName(typeName, Namespaces.SYSTEM_NS); _buildDateTimeOffset = true; } else if (typeInfo.IsEnum) { xsTypename = new XmlQualifiedName(typeName, _xmlNamespaceManager.LookupNamespace("tns")); _enumToBuild.Enqueue(type); } else if (underlyingType?.IsEnum == true) { xsTypename = new XmlQualifiedName(underlyingType.GetSerializedTypeName(), _xmlNamespaceManager.LookupNamespace("tns")); _enumToBuild.Enqueue(underlyingType); } else { if (underlyingType != null) { xsTypename = ResolveType(underlyingType); writer.WriteAttributeString("nillable", "true"); } else { xsTypename = ResolveType(type); } } if (isAttribute) { // skip occurence } else if (isArray) { writer.WriteAttributeString("minOccurs", "0"); writer.WriteAttributeString("maxOccurs", "unbounded"); writer.WriteAttributeString("nillable", "true"); } else { writer.WriteAttributeString("minOccurs", type.IsValueType ? "1" : "0"); writer.WriteAttributeString("maxOccurs", "1"); } if (string.IsNullOrEmpty(name)) { name = xsTypename.Name; } writer.WriteAttributeString("name", name); writer.WriteAttributeString("type", $"{_xmlNamespaceManager.LookupPrefix(xsTypename.Namespace)}:{xsTypename.Name}"); } else { var newTypeToBuild = new TypeToBuild(type); if (!string.IsNullOrWhiteSpace(toBuild.ChildElementName)) { newTypeToBuild.ChildElementName = toBuild.ChildElementName; SetUniqueNameForDynamicType(newTypeToBuild); } writer.WriteAttributeString("minOccurs", "0"); if (isArray) { writer.WriteAttributeString("maxOccurs", "unbounded"); writer.WriteAttributeString("nillable", "true"); } else { writer.WriteAttributeString("maxOccurs", "1"); } if (type == typeof(Stream) || typeof(Stream).IsAssignableFrom(type)) { name = "StreamBody"; writer.WriteAttributeString("name", name); writer.WriteAttributeString("type", $"{_xmlNamespaceManager.LookupPrefix(Namespaces.XMLNS_XSD)}:base64Binary"); } else if (type.IsArray) { if (string.IsNullOrEmpty(name)) { name = typeName; } writer.WriteAttributeString("name", name); writer.WriteAttributeString("type", "tns:" + newTypeToBuild.TypeName); _complexTypeToBuild.Enqueue(newTypeToBuild); } else if (typeof(IEnumerable).IsAssignableFrom(type)) { if (type.GetGenericType().Name == "String") { if (string.IsNullOrEmpty(name)) { name = typeName; } var ns = $"q{_namespaceCounter++}"; writer.WriteXmlnsAttribute(ns, Namespaces.ARRAYS_NS); writer.WriteAttributeString("name", name); writer.WriteAttributeString("nillable", "true"); writer.WriteAttributeString("type", $"{ns}:{newTypeToBuild.TypeName}"); _arrayToBuild.Enqueue(type); } else { if (string.IsNullOrEmpty(name)) { name = typeName; } writer.WriteAttributeString("name", name); if (!isArray) { writer.WriteAttributeString("nillable", "true"); } if (isListWithoutWrapper) { newTypeToBuild = new TypeToBuild(newTypeToBuild.Type.GetGenericType()); } if (newTypeToBuild.IsAnonumous) { AddSchemaComplexType(writer, newTypeToBuild); } else { writer.WriteAttributeString("type", "tns:" + newTypeToBuild.TypeName); _complexTypeToBuild.Enqueue(newTypeToBuild); } } } else if (toBuild.IsAnonumous) { writer.WriteAttributeString("name", name); AddSchemaComplexType(writer, newTypeToBuild); } else { if (string.IsNullOrEmpty(name)) { name = typeName; } writer.WriteAttributeString("name", name); writer.WriteAttributeString("type", "tns:" + newTypeToBuild.TypeName); _complexTypeToBuild.Enqueue(newTypeToBuild); } } writer.WriteEndElement(); // element }
private void AddSchemaTypeProperty(XmlDictionaryWriter writer, PropertyInfo property, TypeToBuild parentTypeToBuild) { if (property.IsChoice()) { writer.WriteStartElement("choice", Namespaces.XMLNS_XSD); if (property.PropertyType.IsEnumerableType()) { writer.WriteAttributeString("minOccurs", "0"); writer.WriteAttributeString("maxOccurs", "unbounded"); } var choiceElements = property.GetCustomAttributes <XmlElementAttribute>(); foreach (var choiceElement in choiceElements) { if (choiceElement != null) { AddSchemaType(writer, choiceElement.Type ?? property.PropertyType, choiceElement.ElementName ?? property.Name); } } writer.WriteEndElement(); // choice return; } var createListWithoutProxyType = false; var toBuild = new TypeToBuild(property.PropertyType); var arrayItem = property.GetCustomAttribute <XmlArrayItemAttribute>(); if (arrayItem != null && !string.IsNullOrWhiteSpace(arrayItem.ElementName)) { toBuild.ChildElementName = arrayItem.ElementName; } var elementItem = property.GetCustomAttribute <XmlElementAttribute>(); if (elementItem != null && !string.IsNullOrWhiteSpace(elementItem.ElementName)) { toBuild.ChildElementName = elementItem.ElementName; createListWithoutProxyType = toBuild.Type.IsEnumerableType(); } var attributeItem = property.GetCustomAttribute <XmlAttributeAttribute>(); var messageBodyMemberAttribute = property.GetCustomAttribute <MessageBodyMemberAttribute>(); if (attributeItem != null) { var name = attributeItem.AttributeName; if (string.IsNullOrWhiteSpace(name)) { name = property.Name; } AddSchemaType(writer, toBuild, name, isAttribute: true); } else if (messageBodyMemberAttribute != null) { var name = messageBodyMemberAttribute.Name; if (string.IsNullOrWhiteSpace(name)) { name = property.Name; } AddSchemaType(writer, toBuild, name, isArray: createListWithoutProxyType, isListWithoutWrapper: createListWithoutProxyType); } else { AddSchemaType(writer, toBuild, parentTypeToBuild.ChildElementName ?? property.Name, isArray: createListWithoutProxyType, isListWithoutWrapper: createListWithoutProxyType); } }
private void AddSchemaComplexType(XmlDictionaryWriter writer, TypeToBuild toBuild) { var toBuildType = toBuild.Type; var toBuildBodyType = GetMessageContractBodyType(toBuildType); var isWrappedBodyType = IsWrappedMessageContractType(toBuildType); var toBuildName = toBuild.TypeName; if (toBuild.IsAnonumous || !_builtComplexTypes.Contains(toBuildName)) { writer.WriteStartElement("complexType", Namespaces.XMLNS_XSD); if (!toBuild.IsAnonumous) { writer.WriteAttributeString("name", toBuildName); } if (toBuildType.IsArray) { writer.WriteStartElement("sequence", Namespaces.XMLNS_XSD); AddSchemaType(writer, toBuildType.GetElementType(), toBuild.ChildElementName, true); writer.WriteEndElement(); // sequence } else if (typeof(IEnumerable).IsAssignableFrom(toBuildType)) { writer.WriteStartElement("sequence", Namespaces.XMLNS_XSD); AddSchemaType(writer, toBuildType.GetGenericType(), toBuild.ChildElementName, true); writer.WriteEndElement(); // sequence } else { if (!isWrappedBodyType) { var properties = toBuildBodyType.GetProperties().Where(prop => !prop.IsIgnored()) .ToList(); var elements = properties.Where(t => !t.IsAttribute()).ToList(); if (elements.Any()) { writer.WriteStartElement("sequence", Namespaces.XMLNS_XSD); foreach (var element in elements) { AddSchemaTypeProperty(writer, element, toBuild); } writer.WriteEndElement(); // sequence } var attributes = properties.Where(t => t.IsAttribute()); foreach (var attribute in attributes) { AddSchemaTypeProperty(writer, attribute, toBuild); } } else { var properties = toBuildType.GetProperties().Where(prop => !prop.IsIgnored()) .ToList(); var elements = properties.Where(t => !t.IsAttribute()).ToList(); if (elements.Any()) { writer.WriteStartElement("sequence", Namespaces.XMLNS_XSD); foreach (var element in elements) { AddSchemaTypeProperty(writer, element, toBuild); } writer.WriteEndElement(); // sequence } var attributes = properties.Where(t => t.IsAttribute()); foreach (var attribute in attributes) { AddSchemaTypeProperty(writer, attribute, toBuild); } var messageBodyMemberFields = toBuildType.GetFields() .Where(field => field.CustomAttributes.Any(attr => attr.AttributeType == typeof(MessageBodyMemberAttribute))) .OrderBy(field => field.GetCustomAttribute <MessageBodyMemberAttribute>().Order); foreach (var field in messageBodyMemberFields) { var messageBodyMember = field.GetCustomAttribute <MessageBodyMemberAttribute>(); var fieldName = messageBodyMember.Name ?? field.Name; AddSchemaType(writer, field.FieldType, fieldName); } } } writer.WriteEndElement(); // complexType if (isWrappedBodyType) { writer.WriteStartElement("element", Namespaces.XMLNS_XSD); writer.WriteAttributeString("name", toBuildName); writer.WriteAttributeString("nillable", "true"); writer.WriteAttributeString("type", "tns:" + toBuildName); writer.WriteEndElement(); // element } _builtComplexTypes.Add(toBuildName); } }