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 AddSchemaType(XmlDictionaryWriter writer, Type type, string name, bool isArray = false, string @namespace = null) { var typeInfo = type.GetTypeInfo(); if (typeInfo.IsByRef) { type = typeInfo.GetElementType(); } var typeName = GetSerialsedTypeName(type); if (writer.TryAddSchemaTypeFromXmlSchemaProviderAttribute(type, name, SoapSerializer.XmlSerializer, _xmlNamespaceManager)) { return; } writer.WriteStartElement("element", Namespaces.XMLNS_XSD); // Check for null, since we may use empty NS if (@namespace != null) { writer.WriteAttributeString("targetNamespace", @namespace); } else if (typeInfo.IsEnum || (typeInfo.IsValueType && 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 { var underlyingType = Nullable.GetUnderlyingType(type); if (underlyingType != null) { xsTypename = ResolveType(underlyingType); writer.WriteAttributeString("nillable", "true"); } else { xsTypename = ResolveType(type); } } 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 { 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:" + typeName); _complexTypeToBuild.Enqueue(type); } else if (typeof(IEnumerable).IsAssignableFrom(type)) { if (GetGenericType(type).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}:{typeName.ToLower()}"); _arrayToBuild.Enqueue(type); } else { if (string.IsNullOrEmpty(name)) { name = typeName; } writer.WriteAttributeString("name", name); if (!isArray) { writer.WriteAttributeString("nillable", "true"); } writer.WriteAttributeString("type", "tns:" + typeName); _complexTypeToBuild.Enqueue(type); } } else { if (string.IsNullOrEmpty(name)) { name = typeName; } writer.WriteAttributeString("name", name); writer.WriteAttributeString("type", "tns:" + typeName); _complexTypeToBuild.Enqueue(type); } } writer.WriteEndElement(); // element }