2 namespace System.Runtime.Serialization
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.Collections.ObjectModel;
8 using System.Diagnostics;
9 using System.Globalization;
11 using System.Reflection;
12 using System.Runtime.Diagnostics;
13 using System.Security;
15 using System.Xml.Schema;
16 using System.Xml.Serialization;
17 using System.Runtime.Serialization.Diagnostics;
21 internal static void GetXmlTypeInfo(Type type, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot)
23 if (IsSpecialXmlType(type, out stableName, out xsdType, out hasRoot))
25 XmlSchemaSet schemas = new XmlSchemaSet();
26 schemas.XmlResolver = null;
27 InvokeSchemaProviderMethod(type, schemas, out stableName, out xsdType, out hasRoot);
28 if (stableName.Name == null || stableName.Name.Length == 0)
29 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidXmlDataContractName, DataContract.GetClrTypeFullName(type))));
32 internal static bool IsSpecialXmlType(Type type, out XmlQualifiedName typeName, out XmlSchemaType xsdType, out bool hasRoot)
36 if (type == Globals.TypeOfXmlElement || type == Globals.TypeOfXmlNodeArray)
39 if (type == Globals.TypeOfXmlElement)
41 xsdType = CreateAnyElementType();
47 xsdType = CreateAnyType();
48 name = "ArrayOfXmlNode";
51 typeName = new XmlQualifiedName(name, DataContract.GetDefaultStableNamespace(type));
58 static bool InvokeSchemaProviderMethod(Type clrType, XmlSchemaSet schemas, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot)
62 object[] attrs = clrType.GetCustomAttributes(Globals.TypeOfXmlSchemaProviderAttribute, false);
63 if (attrs == null || attrs.Length == 0)
65 stableName = DataContract.GetDefaultStableName(clrType);
69 XmlSchemaProviderAttribute provider = (XmlSchemaProviderAttribute)attrs[0];
72 xsdType = CreateAnyElementType();
75 string methodName = provider.MethodName;
76 if (methodName == null || methodName.Length == 0)
79 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidGetSchemaMethod, DataContract.GetClrTypeFullName(clrType))));
80 stableName = DataContract.GetDefaultStableName(clrType);
84 MethodInfo getMethod = clrType.GetMethod(methodName, /*BindingFlags.DeclaredOnly |*/ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(XmlSchemaSet) }, null);
85 if (getMethod == null)
86 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.MissingGetSchemaMethod, DataContract.GetClrTypeFullName(clrType), methodName)));
88 if (!(Globals.TypeOfXmlQualifiedName.IsAssignableFrom(getMethod.ReturnType)) && !(Globals.TypeOfXmlSchemaType.IsAssignableFrom(getMethod.ReturnType)))
89 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidReturnTypeOnGetSchemaMethod, DataContract.GetClrTypeFullName(clrType), methodName, DataContract.GetClrTypeFullName(getMethod.ReturnType), DataContract.GetClrTypeFullName(Globals.TypeOfXmlQualifiedName), typeof(XmlSchemaType))));
91 object typeInfo = getMethod.Invoke(null, new object[] { schemas });
96 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidNonNullReturnValueByIsAny, DataContract.GetClrTypeFullName(clrType), methodName)));
97 stableName = DataContract.GetDefaultStableName(clrType);
99 else if (typeInfo == null)
101 xsdType = CreateAnyElementType();
103 stableName = DataContract.GetDefaultStableName(clrType);
107 XmlSchemaType providerXsdType = typeInfo as XmlSchemaType;
108 if (providerXsdType != null)
110 string typeName = providerXsdType.Name;
111 string typeNs = null;
112 if (typeName == null || typeName.Length == 0)
114 DataContract.GetDefaultStableName(DataContract.GetClrTypeFullName(clrType), out typeName, out typeNs);
115 stableName = new XmlQualifiedName(typeName, typeNs);
116 providerXsdType.Annotation = GetSchemaAnnotation(ExportActualType(stableName, new XmlDocument()));
117 xsdType = providerXsdType;
121 foreach (XmlSchema schema in schemas.Schemas())
123 foreach (XmlSchemaObject schemaItem in schema.Items)
125 if ((object)schemaItem == (object)providerXsdType)
127 typeNs = schema.TargetNamespace;
129 typeNs = String.Empty;
137 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.MissingSchemaType, typeName, DataContract.GetClrTypeFullName(clrType))));
138 stableName = new XmlQualifiedName(typeName, typeNs);
142 stableName = (XmlQualifiedName)typeInfo;
148 static XmlSchemaComplexType CreateAnyElementType()
150 XmlSchemaComplexType anyElementType = new XmlSchemaComplexType();
151 anyElementType.IsMixed = false;
152 anyElementType.Particle = new XmlSchemaSequence();
153 XmlSchemaAny any = new XmlSchemaAny();
155 any.ProcessContents = XmlSchemaContentProcessing.Lax;
156 ((XmlSchemaSequence)anyElementType.Particle).Items.Add(any);
157 return anyElementType;
160 static XmlSchemaAnnotation GetSchemaAnnotation(params XmlNode[] nodes)
162 if (nodes == null || nodes.Length == 0)
164 bool hasAnnotation = false;
165 for (int i = 0; i < nodes.Length; i++)
166 if (nodes[i] != null)
168 hasAnnotation = true;
174 XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();
175 XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();
176 annotation.Items.Add(appInfo);
177 appInfo.Markup = nodes;
181 static XmlSchemaComplexType CreateAnyType()
183 XmlSchemaComplexType anyType = new XmlSchemaComplexType();
184 anyType.IsMixed = true;
185 anyType.Particle = new XmlSchemaSequence();
186 XmlSchemaAny any = new XmlSchemaAny();
188 any.MaxOccurs = Decimal.MaxValue;
189 any.ProcessContents = XmlSchemaContentProcessing.Lax;
190 ((XmlSchemaSequence)anyType.Particle).Items.Add(any);
191 anyType.AnyAttribute = new XmlSchemaAnyAttribute();
195 static XmlElement ExportActualType(XmlQualifiedName typeName, XmlDocument xmlDoc)
197 XmlElement actualTypeElement = xmlDoc.CreateElement(ActualTypeAnnotationName.Name, ActualTypeAnnotationName.Namespace);
199 XmlAttribute nameAttribute = xmlDoc.CreateAttribute(Globals.ActualTypeNameAttribute);
200 nameAttribute.Value = typeName.Name;
201 actualTypeElement.Attributes.Append(nameAttribute);
203 XmlAttribute nsAttribute = xmlDoc.CreateAttribute(Globals.ActualTypeNamespaceAttribute);
204 nsAttribute.Value = typeName.Namespace;
205 actualTypeElement.Attributes.Append(nsAttribute);
207 return actualTypeElement;
210 static XmlQualifiedName actualTypeAnnotationName;
211 internal static XmlQualifiedName ActualTypeAnnotationName
215 if (actualTypeAnnotationName == null)
216 actualTypeAnnotationName = new XmlQualifiedName(Globals.ActualTypeLocalName, Globals.SerializationNamespace);
217 return actualTypeAnnotationName;