Пример #1
0
        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
        }
Пример #2
0
        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
        }