1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Runtime.Serialization
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Collections.ObjectModel;
11 using System.Diagnostics;
12 using System.Globalization;
14 using System.Security;
15 using System.Runtime.Diagnostics;
17 using System.Xml.Schema;
18 using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
19 using SchemaObjectDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, SchemaObjectInfo>;
20 using System.Runtime.Serialization.Diagnostics;
24 DataContractSet dataContractSet;
25 XmlSchemaSet schemaSet;
26 ICollection<XmlQualifiedName> typeNames;
27 ICollection<XmlSchemaElement> elements;
28 XmlQualifiedName[] elementTypeNames;
29 bool importXmlDataType;
30 SchemaObjectDictionary schemaObjects;
31 List<XmlSchemaRedefine> redefineList;
32 bool needToImportKnownTypesForObject;
34 [Fx.Tag.SecurityNote(Critical = "Static field used to store serialization schema elements from future versions."
35 + " Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
37 static Hashtable serializationSchemaElements;
39 internal SchemaImporter(XmlSchemaSet schemas, ICollection<XmlQualifiedName> typeNames, ICollection<XmlSchemaElement> elements, XmlQualifiedName[] elementTypeNames, DataContractSet dataContractSet, bool importXmlDataType)
41 this.dataContractSet = dataContractSet;
42 this.schemaSet = schemas;
43 this.typeNames = typeNames;
44 this.elements = elements;
45 this.elementTypeNames = elementTypeNames;
46 this.importXmlDataType = importXmlDataType;
49 internal void Import()
51 if (!schemaSet.Contains(Globals.SerializationNamespace))
53 StringReader reader = new StringReader(Globals.SerializationSchema);
54 XmlSchema schema = XmlSchema.Read(new XmlTextReader(reader) { DtdProcessing = DtdProcessing.Prohibit }, null);
56 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CouldNotReadSerializationSchema, Globals.SerializationNamespace)));
57 schemaSet.Add(schema);
62 CompileSchemaSet(schemaSet);
64 #pragma warning suppress 56500 // covered by FxCOP
71 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportInvalidSchemas), ex));
74 if (typeNames == null)
76 ICollection schemaList = schemaSet.Schemas();
77 foreach (object schemaObj in schemaList)
79 if (schemaObj == null)
80 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportNullSchema)));
82 XmlSchema schema = (XmlSchema)schemaObj;
83 if (schema.TargetNamespace != Globals.SerializationNamespace
84 && schema.TargetNamespace != Globals.SchemaNamespace)
86 foreach (XmlSchemaObject typeObj in schema.SchemaTypes.Values)
88 ImportType((XmlSchemaType)typeObj);
90 foreach (XmlSchemaElement element in schema.Elements.Values)
92 if (element.SchemaType != null)
93 ImportAnonymousGlobalElement(element, element.QualifiedName, schema.TargetNamespace);
100 foreach (XmlQualifiedName typeName in typeNames)
102 if (typeName == null)
103 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportNullDataContractName)));
104 ImportType(typeName);
107 if (elements != null)
110 foreach (XmlSchemaElement element in elements)
112 XmlQualifiedName typeName = element.SchemaTypeName;
113 if (typeName != null && typeName.Name.Length > 0)
115 elementTypeNames[i++] = ImportType(typeName).StableName;
119 XmlSchema schema = SchemaHelper.GetSchemaWithGlobalElementDeclaration(element, schemaSet);
122 elementTypeNames[i++] = ImportAnonymousElement(element, element.QualifiedName).StableName;
126 elementTypeNames[i++] = ImportAnonymousGlobalElement(element, element.QualifiedName, schema.TargetNamespace).StableName;
132 ImportKnownTypesForObject();
135 internal static void CompileSchemaSet(XmlSchemaSet schemaSet)
137 if (schemaSet.Contains(XmlSchema.Namespace))
141 // Add base XSD schema with top level element named "schema"
142 XmlSchema xsdSchema = new XmlSchema();
143 xsdSchema.TargetNamespace = XmlSchema.Namespace;
144 XmlSchemaElement element = new XmlSchemaElement();
145 element.Name = Globals.SchemaLocalName;
146 element.SchemaType = new XmlSchemaComplexType();
147 xsdSchema.Items.Add(element);
148 schemaSet.Add(xsdSchema);
153 SchemaObjectDictionary SchemaObjects
157 if (schemaObjects == null)
158 schemaObjects = CreateSchemaObjects();
159 return schemaObjects;
163 List<XmlSchemaRedefine> RedefineList
167 if (redefineList == null)
168 redefineList = CreateRedefineList();
173 void ImportKnownTypes(XmlQualifiedName typeName)
175 SchemaObjectInfo schemaObjectInfo;
176 if (SchemaObjects.TryGetValue(typeName, out schemaObjectInfo))
178 List<XmlSchemaType> knownTypes = schemaObjectInfo.knownTypes;
179 if (knownTypes != null)
181 foreach (XmlSchemaType knownType in knownTypes)
182 ImportType(knownType);
187 internal static bool IsObjectContract(DataContract dataContract)
189 Dictionary<Type, object> previousCollectionTypes = new Dictionary<Type, object>();
190 while (dataContract is CollectionDataContract)
192 if (dataContract.OriginalUnderlyingType == null)
194 dataContract = ((CollectionDataContract)dataContract).ItemContract;
198 if (!previousCollectionTypes.ContainsKey(dataContract.OriginalUnderlyingType))
200 previousCollectionTypes.Add(dataContract.OriginalUnderlyingType, dataContract.OriginalUnderlyingType);
201 dataContract = ((CollectionDataContract)dataContract).ItemContract;
209 return dataContract is PrimitiveDataContract && ((PrimitiveDataContract)dataContract).UnderlyingType == Globals.TypeOfObject;
212 void ImportKnownTypesForObject()
214 if (!needToImportKnownTypesForObject)
216 needToImportKnownTypesForObject = false;
217 if (dataContractSet.KnownTypesForObject == null)
219 SchemaObjectInfo schemaObjectInfo;
220 if (SchemaObjects.TryGetValue(SchemaExporter.AnytypeQualifiedName, out schemaObjectInfo))
222 List<XmlSchemaType> knownTypes = schemaObjectInfo.knownTypes;
223 if (knownTypes != null)
225 DataContractDictionary knownDataContracts = new DataContractDictionary();
226 foreach (XmlSchemaType knownType in knownTypes)
228 // Expected: will throw exception if schema set contains types that are not supported
229 DataContract dataContract = ImportType(knownType);
230 DataContract existingContract;
231 if (!knownDataContracts.TryGetValue(dataContract.StableName, out existingContract))
233 knownDataContracts.Add(dataContract.StableName, dataContract);
236 dataContractSet.KnownTypesForObject = knownDataContracts;
242 internal SchemaObjectDictionary CreateSchemaObjects()
244 SchemaObjectDictionary schemaObjects = new SchemaObjectDictionary();
245 ICollection schemaList = schemaSet.Schemas();
246 List<XmlSchemaType> knownTypesForObject = new List<XmlSchemaType>();
247 schemaObjects.Add(SchemaExporter.AnytypeQualifiedName, new SchemaObjectInfo(null, null, null, knownTypesForObject));
249 foreach (XmlSchema schema in schemaList)
251 if (schema.TargetNamespace != Globals.SerializationNamespace)
253 foreach (XmlSchemaObject schemaObj in schema.SchemaTypes.Values)
255 XmlSchemaType schemaType = schemaObj as XmlSchemaType;
256 if (schemaType != null)
258 knownTypesForObject.Add(schemaType);
260 XmlQualifiedName currentTypeName = new XmlQualifiedName(schemaType.Name, schema.TargetNamespace);
261 SchemaObjectInfo schemaObjectInfo;
262 if (schemaObjects.TryGetValue(currentTypeName, out schemaObjectInfo))
264 schemaObjectInfo.type = schemaType;
265 schemaObjectInfo.schema = schema;
269 schemaObjects.Add(currentTypeName, new SchemaObjectInfo(schemaType, null, schema, null));
272 XmlQualifiedName baseTypeName = GetBaseTypeName(schemaType);
273 if (baseTypeName != null)
275 SchemaObjectInfo baseTypeInfo;
276 if (schemaObjects.TryGetValue(baseTypeName, out baseTypeInfo))
278 if (baseTypeInfo.knownTypes == null)
280 baseTypeInfo.knownTypes = new List<XmlSchemaType>();
285 baseTypeInfo = new SchemaObjectInfo(null, null, null, new List<XmlSchemaType>());
286 schemaObjects.Add(baseTypeName, baseTypeInfo);
288 baseTypeInfo.knownTypes.Add(schemaType);
292 foreach (XmlSchemaObject schemaObj in schema.Elements.Values)
294 XmlSchemaElement schemaElement = schemaObj as XmlSchemaElement;
295 if (schemaElement != null)
297 XmlQualifiedName currentElementName = new XmlQualifiedName(schemaElement.Name, schema.TargetNamespace);
298 SchemaObjectInfo schemaObjectInfo;
299 if (schemaObjects.TryGetValue(currentElementName, out schemaObjectInfo))
301 schemaObjectInfo.element = schemaElement;
302 schemaObjectInfo.schema = schema;
306 schemaObjects.Add(currentElementName, new SchemaObjectInfo(null, schemaElement, schema, null));
312 return schemaObjects;
315 XmlQualifiedName GetBaseTypeName(XmlSchemaType type)
317 XmlQualifiedName baseTypeName = null;
318 XmlSchemaComplexType complexType = type as XmlSchemaComplexType;
319 if (complexType != null)
321 if (complexType.ContentModel != null)
323 XmlSchemaComplexContent complexContent = complexType.ContentModel as XmlSchemaComplexContent;
324 if (complexContent != null)
326 XmlSchemaComplexContentExtension extension = complexContent.Content as XmlSchemaComplexContentExtension;
327 if (extension != null)
328 baseTypeName = extension.BaseTypeName;
335 List<XmlSchemaRedefine> CreateRedefineList()
337 List<XmlSchemaRedefine> list = new List<XmlSchemaRedefine>();
339 ICollection schemaList = schemaSet.Schemas();
340 foreach (object schemaObj in schemaList)
342 XmlSchema schema = schemaObj as XmlSchema;
345 foreach (XmlSchemaExternal ext in schema.Includes)
347 XmlSchemaRedefine redefine = ext as XmlSchemaRedefine;
348 if (redefine != null)
356 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on XmlDataContract.",
357 Safe = "Called during schema import/code generation.")]
358 [SecuritySafeCritical]
359 DataContract ImportAnonymousGlobalElement(XmlSchemaElement element, XmlQualifiedName typeQName, string ns)
361 DataContract contract = ImportAnonymousElement(element, typeQName);
362 XmlDataContract xmlDataContract = contract as XmlDataContract;
363 if (xmlDataContract != null)
365 xmlDataContract.SetTopLevelElementName(new XmlQualifiedName(element.Name, ns));
366 xmlDataContract.IsTopLevelElementNullable = element.IsNillable;
371 DataContract ImportAnonymousElement(XmlSchemaElement element, XmlQualifiedName typeQName)
373 if (SchemaHelper.GetSchemaType(SchemaObjects, typeQName) != null)
375 for (int i = 1;; i++)
377 typeQName = new XmlQualifiedName(typeQName.Name + i.ToString(NumberFormatInfo.InvariantInfo), typeQName.Namespace);
378 if (SchemaHelper.GetSchemaType(SchemaObjects, typeQName) == null)
380 if (i == Int32.MaxValue)
381 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, element.Name)));
384 if (element.SchemaType == null)
385 return ImportType(SchemaExporter.AnytypeQualifiedName);
387 return ImportType(element.SchemaType, typeQName, true/*isAnonymous*/);
390 DataContract ImportType(XmlQualifiedName typeName)
392 DataContract dataContract = DataContract.GetBuiltInDataContract(typeName.Name, typeName.Namespace);
393 if (dataContract == null)
395 XmlSchemaType type = SchemaHelper.GetSchemaType(SchemaObjects, typeName);
397 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SpecifiedTypeNotFoundInSchema, typeName.Name, typeName.Namespace)));
398 dataContract = ImportType(type);
400 if (IsObjectContract(dataContract))
401 needToImportKnownTypesForObject = true;
405 DataContract ImportType(XmlSchemaType type)
407 return ImportType(type, type.QualifiedName, false/*isAnonymous*/);
411 DataContract ImportType(XmlSchemaType type, XmlQualifiedName typeName, bool isAnonymous)
413 DataContract dataContract = dataContractSet[typeName];
414 if (dataContract != null)
417 InvalidDataContractException invalidContractException;
420 foreach (XmlSchemaRedefine redefine in RedefineList)
422 if (redefine.SchemaTypes[typeName] != null)
423 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.RedefineNotSupported));
426 if (type is XmlSchemaSimpleType)
428 XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)type;
429 XmlSchemaSimpleTypeContent content = simpleType.Content;
430 if (content is XmlSchemaSimpleTypeUnion)
431 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.SimpleTypeUnionNotSupported));
432 else if (content is XmlSchemaSimpleTypeList)
433 dataContract = ImportFlagsEnum(typeName, (XmlSchemaSimpleTypeList)content, simpleType.Annotation);
434 else if (content is XmlSchemaSimpleTypeRestriction)
436 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)content;
437 if (CheckIfEnum(restriction))
439 dataContract = ImportEnum(typeName, restriction, false /*isFlags*/, simpleType.Annotation);
443 dataContract = ImportSimpleTypeRestriction(typeName, restriction);
444 if (dataContract.IsBuiltInDataContract && !isAnonymous)
446 dataContractSet.InternalAdd(typeName, dataContract);
451 else if (type is XmlSchemaComplexType)
453 XmlSchemaComplexType complexType = (XmlSchemaComplexType)type;
454 if (complexType.ContentModel == null)
456 CheckComplexType(typeName, complexType);
457 dataContract = ImportType(typeName, complexType.Particle, complexType.Attributes, complexType.AnyAttribute, null /* baseTypeName */, complexType.Annotation);
461 XmlSchemaContentModel contentModel = complexType.ContentModel;
462 if (contentModel is XmlSchemaSimpleContent)
463 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.SimpleContentNotSupported));
464 else if (contentModel is XmlSchemaComplexContent)
466 XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent)contentModel;
467 if (complexContent.IsMixed)
468 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.MixedContentNotSupported));
470 if (complexContent.Content is XmlSchemaComplexContentExtension)
472 XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension)complexContent.Content;
473 dataContract = ImportType(typeName, extension.Particle, extension.Attributes, extension.AnyAttribute, extension.BaseTypeName, complexType.Annotation);
475 else if (complexContent.Content is XmlSchemaComplexContentRestriction)
477 XmlSchemaComplexContentRestriction restriction = (XmlSchemaComplexContentRestriction)complexContent.Content;
478 XmlQualifiedName baseTypeName = restriction.BaseTypeName;
479 if (baseTypeName == SchemaExporter.AnytypeQualifiedName)
480 dataContract = ImportType(typeName, restriction.Particle, restriction.Attributes, restriction.AnyAttribute, null /* baseTypeName */, complexType.Annotation);
482 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ComplexTypeRestrictionNotSupported));
488 if (dataContract == null)
489 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, String.Empty);
490 if (type.QualifiedName != XmlQualifiedName.Empty)
491 ImportTopLevelElement(typeName);
492 ImportDataContractExtension(type, dataContract);
493 ImportGenericInfo(type, dataContract);
494 ImportKnownTypes(typeName);
498 catch (InvalidDataContractException e)
500 invalidContractException = e;
503 // Execution gets to this point if InvalidDataContractException was thrown
504 if (importXmlDataType)
506 RemoveFailedContract(typeName);
507 return ImportXmlDataType(typeName, type, isAnonymous);
510 if (dataContractSet.TryGetReferencedType(typeName, dataContract, out referencedType)
511 || (string.IsNullOrEmpty(type.Name) && dataContractSet.TryGetReferencedType(ImportActualType(type.Annotation, typeName, typeName), dataContract, out referencedType)))
513 if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(referencedType))
515 RemoveFailedContract(typeName);
516 return ImportXmlDataType(typeName, type, isAnonymous);
519 XmlDataContract specialContract = ImportSpecialXmlDataType(type, isAnonymous);
520 if (specialContract != null)
522 this.dataContractSet.Remove(typeName);
523 return specialContract;
526 throw invalidContractException;
529 private void RemoveFailedContract(XmlQualifiedName typeName)
531 ClassDataContract oldContract = this.dataContractSet[typeName] as ClassDataContract;
532 this.dataContractSet.Remove(typeName);
533 if (oldContract != null)
535 ClassDataContract ancestorDataContract = oldContract.BaseContract;
536 while (ancestorDataContract != null)
538 ancestorDataContract.KnownDataContracts.Remove(typeName);
539 ancestorDataContract = ancestorDataContract.BaseContract;
541 if (dataContractSet.KnownTypesForObject != null)
542 dataContractSet.KnownTypesForObject.Remove(typeName);
546 bool CheckIfEnum(XmlSchemaSimpleTypeRestriction restriction)
548 foreach (XmlSchemaFacet facet in restriction.Facets)
550 if (!(facet is XmlSchemaEnumerationFacet))
554 XmlQualifiedName expectedBase = SchemaExporter.StringQualifiedName;
555 if (restriction.BaseTypeName != XmlQualifiedName.Empty)
557 return ((restriction.BaseTypeName == expectedBase && restriction.Facets.Count > 0) || ImportType(restriction.BaseTypeName) is EnumDataContract);
559 else if (restriction.BaseType != null)
561 DataContract baseContract = ImportType(restriction.BaseType);
562 return (baseContract.StableName == expectedBase || baseContract is EnumDataContract);
568 bool CheckIfCollection(XmlSchemaSequence rootSequence)
570 if (rootSequence.Items == null || rootSequence.Items.Count == 0)
572 RemoveOptionalUnknownSerializationElements(rootSequence.Items);
573 if (rootSequence.Items.Count != 1)
576 XmlSchemaObject o = rootSequence.Items[0];
577 if (!(o is XmlSchemaElement))
580 XmlSchemaElement localElement = (XmlSchemaElement)o;
581 return (localElement.MaxOccursString == Globals.OccursUnbounded || localElement.MaxOccurs > 1);
584 bool CheckIfISerializable(XmlSchemaSequence rootSequence, XmlSchemaObjectCollection attributes)
586 if (rootSequence.Items == null || rootSequence.Items.Count == 0)
589 RemoveOptionalUnknownSerializationElements(rootSequence.Items);
591 if (attributes == null || attributes.Count == 0)
594 return (rootSequence.Items.Count == 1 && rootSequence.Items[0] is XmlSchemaAny);
597 [Fx.Tag.SecurityNote(Critical = "Initializes critical static fields.",
598 Safe = "Doesn't leak anything.")]
599 [SecuritySafeCritical]
600 void RemoveOptionalUnknownSerializationElements(XmlSchemaObjectCollection items)
602 for (int i = 0; i < items.Count; i++)
604 XmlSchemaElement element = items[i] as XmlSchemaElement;
605 if (element != null && element.RefName != null &&
606 element.RefName.Namespace == Globals.SerializationNamespace &&
607 element.MinOccurs == 0)
609 if (serializationSchemaElements == null)
611 XmlSchema serializationSchema = XmlSchema.Read(XmlReader.Create(new StringReader(Globals.SerializationSchema)), null);
612 serializationSchemaElements = new Hashtable();
613 foreach (XmlSchemaObject schemaObject in serializationSchema.Items)
615 XmlSchemaElement schemaElement = schemaObject as XmlSchemaElement;
616 if (schemaElement != null)
617 serializationSchemaElements.Add(schemaElement.Name, schemaElement);
620 if (!serializationSchemaElements.ContainsKey(element.RefName.Name))
629 DataContract ImportType(XmlQualifiedName typeName, XmlSchemaParticle rootParticle, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlQualifiedName baseTypeName, XmlSchemaAnnotation annotation)
631 DataContract dataContract = null;
632 bool isDerived = (baseTypeName != null);
635 ImportAttributes(typeName, attributes, anyAttribute, out isReference);
637 if (rootParticle == null)
638 dataContract = ImportClass(typeName, new XmlSchemaSequence(), baseTypeName, annotation, isReference);
639 else if (!(rootParticle is XmlSchemaSequence))
640 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.RootParticleMustBeSequence));
643 XmlSchemaSequence rootSequence = (XmlSchemaSequence)rootParticle;
644 if (rootSequence.MinOccurs != 1)
645 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.RootSequenceMustBeRequired));
646 if (rootSequence.MaxOccurs != 1)
647 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.RootSequenceMaxOccursMustBe));
649 if (!isDerived && CheckIfCollection(rootSequence))
650 dataContract = ImportCollection(typeName, rootSequence, attributes, annotation, isReference);
651 else if (CheckIfISerializable(rootSequence, attributes))
652 dataContract = ImportISerializable(typeName, rootSequence, baseTypeName, attributes, annotation);
654 dataContract = ImportClass(typeName, rootSequence, baseTypeName, annotation, isReference);
659 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on ClassDataContract.",
660 Safe = "Called during schema import/code generation.")]
661 [SecuritySafeCritical]
662 ClassDataContract ImportClass(XmlQualifiedName typeName, XmlSchemaSequence rootSequence, XmlQualifiedName baseTypeName, XmlSchemaAnnotation annotation, bool isReference)
664 ClassDataContract dataContract = new ClassDataContract();
665 dataContract.StableName = typeName;
666 AddDataContract(dataContract);
668 dataContract.IsValueType = IsValueType(typeName, annotation);
669 dataContract.IsReference = isReference;
670 if (baseTypeName != null)
672 ImportBaseContract(baseTypeName, dataContract);
673 if (dataContract.BaseContract.IsISerializable)
675 if (IsISerializableDerived(typeName, rootSequence))
676 dataContract.IsISerializable = true;
678 ThrowTypeCannotBeImportedException(dataContract.StableName.Name, dataContract.StableName.Namespace, SR.GetString(SR.DerivedTypeNotISerializable, baseTypeName.Name, baseTypeName.Namespace));
680 if (dataContract.BaseContract.IsReference)
682 dataContract.IsReference = true;
686 if (!dataContract.IsISerializable)
688 dataContract.Members = new List<DataMember>();
689 RemoveOptionalUnknownSerializationElements(rootSequence.Items);
690 for (int memberIndex = 0; memberIndex < rootSequence.Items.Count; memberIndex++)
692 XmlSchemaElement element = rootSequence.Items[memberIndex] as XmlSchemaElement;
694 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.MustContainOnlyLocalElements));
695 ImportClassMember(element, dataContract);
702 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on XmlDataContract.",
703 Safe = "Called during schema import/code generation.")]
704 [SecuritySafeCritical]
705 DataContract ImportXmlDataType(XmlQualifiedName typeName, XmlSchemaType xsdType, bool isAnonymous)
707 DataContract dataContract = dataContractSet[typeName];
708 if (dataContract != null)
711 XmlDataContract xmlDataContract = ImportSpecialXmlDataType(xsdType, isAnonymous);
712 if (xmlDataContract != null)
713 return xmlDataContract;
715 xmlDataContract = new XmlDataContract();
716 xmlDataContract.StableName = typeName;
717 xmlDataContract.IsValueType = false;
718 AddDataContract(xmlDataContract);
721 ImportDataContractExtension(xsdType, xmlDataContract);
722 xmlDataContract.IsValueType = IsValueType(typeName, xsdType.Annotation);
723 xmlDataContract.IsTypeDefinedOnImport = true;
724 xmlDataContract.XsdType = isAnonymous ? xsdType : null;
725 xmlDataContract.HasRoot = !IsXmlAnyElementType(xsdType as XmlSchemaComplexType);
729 //Value type can be used by both nillable and non-nillable elements but reference type cannot be used by non nillable elements
730 xmlDataContract.IsValueType = true;
731 xmlDataContract.IsTypeDefinedOnImport = false;
732 xmlDataContract.HasRoot = true;
733 if (DiagnosticUtility.ShouldTraceVerbose)
735 TraceUtility.Trace(TraceEventType.Verbose, TraceCode.XsdImportAnnotationFailed,
736 SR.GetString(SR.TraceCodeXsdImportAnnotationFailed), new StringTraceRecord("Type", typeName.Namespace + ":" + typeName.Name));
742 xmlDataContract.SetTopLevelElementName(SchemaHelper.GetGlobalElementDeclaration(schemaSet, typeName, out isNullable));
743 xmlDataContract.IsTopLevelElementNullable = isNullable;
745 return xmlDataContract;
748 private XmlDataContract ImportSpecialXmlDataType(XmlSchemaType xsdType, bool isAnonymous)
752 XmlSchemaComplexType complexType = xsdType as XmlSchemaComplexType;
753 if (complexType == null)
755 if (IsXmlAnyElementType(complexType))
757 //check if the type is XElement
758 XmlQualifiedName xlinqTypeName = new XmlQualifiedName("XElement", "http://schemas.datacontract.org/2004/07/System.Xml.Linq");
760 if (dataContractSet.TryGetReferencedType(xlinqTypeName, null, out referencedType)
761 && Globals.TypeOfIXmlSerializable.IsAssignableFrom(referencedType))
763 XmlDataContract xmlDataContract = new XmlDataContract(referencedType);
764 AddDataContract(xmlDataContract);
765 return xmlDataContract;
767 //otherwise, assume XmlElement
768 return (XmlDataContract)DataContract.GetBuiltInDataContract(Globals.TypeOfXmlElement);
770 if (IsXmlAnyType(complexType))
771 return (XmlDataContract)DataContract.GetBuiltInDataContract(Globals.TypeOfXmlNodeArray);
775 bool IsXmlAnyElementType(XmlSchemaComplexType xsdType)
780 XmlSchemaSequence sequence = xsdType.Particle as XmlSchemaSequence;
781 if (sequence == null)
784 if (sequence.Items == null || sequence.Items.Count != 1)
787 XmlSchemaAny any = sequence.Items[0] as XmlSchemaAny;
788 if (any == null || any.Namespace != null)
791 if (xsdType.AnyAttribute != null || (xsdType.Attributes != null && xsdType.Attributes.Count > 0))
797 bool IsXmlAnyType(XmlSchemaComplexType xsdType)
802 XmlSchemaSequence sequence = xsdType.Particle as XmlSchemaSequence;
803 if (sequence == null)
806 if (sequence.Items == null || sequence.Items.Count != 1)
809 XmlSchemaAny any = sequence.Items[0] as XmlSchemaAny;
810 if (any == null || any.Namespace != null)
813 if (any.MaxOccurs != Decimal.MaxValue)
816 if (xsdType.AnyAttribute == null || xsdType.Attributes.Count > 0)
822 bool IsValueType(XmlQualifiedName typeName, XmlSchemaAnnotation annotation)
824 string isValueTypeInnerText = GetInnerText(typeName, ImportAnnotation(annotation, SchemaExporter.IsValueTypeName));
825 if (isValueTypeInnerText != null)
829 return XmlConvert.ToBoolean(isValueTypeInnerText);
831 catch (FormatException fe)
833 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.IsValueTypeFormattedIncorrectly, isValueTypeInnerText, fe.Message));
839 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on ClassDataContract.",
840 Safe = "Called during schema import/code generation.")]
841 [SecuritySafeCritical]
842 ClassDataContract ImportISerializable(XmlQualifiedName typeName, XmlSchemaSequence rootSequence, XmlQualifiedName baseTypeName, XmlSchemaObjectCollection attributes, XmlSchemaAnnotation annotation)
844 ClassDataContract dataContract = new ClassDataContract();
845 dataContract.StableName = typeName;
846 dataContract.IsISerializable = true;
847 AddDataContract(dataContract);
849 dataContract.IsValueType = IsValueType(typeName, annotation);
850 if (baseTypeName == null)
851 CheckISerializableBase(typeName, rootSequence, attributes);
854 ImportBaseContract(baseTypeName, dataContract);
855 if (!dataContract.BaseContract.IsISerializable)
856 ThrowISerializableTypeCannotBeImportedException(dataContract.StableName.Name, dataContract.StableName.Namespace, SR.GetString(SR.BaseTypeNotISerializable, baseTypeName.Name, baseTypeName.Namespace));
857 if (!IsISerializableDerived(typeName, rootSequence))
858 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableDerivedContainsOneOrMoreItems));
864 void CheckISerializableBase(XmlQualifiedName typeName, XmlSchemaSequence rootSequence, XmlSchemaObjectCollection attributes)
866 if (rootSequence == null)
867 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableDoesNotContainAny));
869 if (rootSequence.Items == null || rootSequence.Items.Count < 1)
870 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableDoesNotContainAny));
871 else if (rootSequence.Items.Count > 1)
872 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableContainsMoreThanOneItems));
874 XmlSchemaObject o = rootSequence.Items[0];
875 if (!(o is XmlSchemaAny))
876 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableDoesNotContainAny));
878 XmlSchemaAny wildcard = (XmlSchemaAny)o;
879 XmlSchemaAny iSerializableWildcardElement = SchemaExporter.ISerializableWildcardElement;
880 if (wildcard.MinOccurs != iSerializableWildcardElement.MinOccurs)
881 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableWildcardMinOccursMustBe, iSerializableWildcardElement.MinOccurs));
882 if (wildcard.MaxOccursString != iSerializableWildcardElement.MaxOccursString)
883 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableWildcardMaxOccursMustBe, iSerializableWildcardElement.MaxOccursString));
884 if (wildcard.Namespace != iSerializableWildcardElement.Namespace)
885 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableWildcardNamespaceInvalid, iSerializableWildcardElement.Namespace));
886 if (wildcard.ProcessContents != iSerializableWildcardElement.ProcessContents)
887 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableWildcardProcessContentsInvalid, iSerializableWildcardElement.ProcessContents));
889 XmlQualifiedName factoryTypeAttributeRefName = SchemaExporter.ISerializableFactoryTypeAttribute.RefName;
890 bool containsFactoryTypeAttribute = false;
891 if (attributes != null)
893 for (int i = 0; i < attributes.Count; i++)
896 if (o is XmlSchemaAttribute)
898 if (((XmlSchemaAttribute)o).RefName == factoryTypeAttributeRefName)
900 containsFactoryTypeAttribute = true;
906 if (!containsFactoryTypeAttribute)
907 ThrowISerializableTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ISerializableMustRefFactoryTypeAttribute, factoryTypeAttributeRefName.Name, factoryTypeAttributeRefName.Namespace));
910 bool IsISerializableDerived(XmlQualifiedName typeName, XmlSchemaSequence rootSequence)
912 return (rootSequence == null || rootSequence.Items == null || rootSequence.Items.Count == 0);
915 [Fx.Tag.SecurityNote(Critical = "Sets critical BaseContract property on ClassDataContract.",
916 Safe = "Called during schema import/code generation.")]
917 [SecuritySafeCritical]
918 void ImportBaseContract(XmlQualifiedName baseTypeName, ClassDataContract dataContract)
920 ClassDataContract baseContract = ImportType(baseTypeName) as ClassDataContract;
921 if (baseContract == null)
922 ThrowTypeCannotBeImportedException(dataContract.StableName.Name, dataContract.StableName.Namespace, SR.GetString(dataContract.IsISerializable ? SR.InvalidISerializableDerivation : SR.InvalidClassDerivation, baseTypeName.Name, baseTypeName.Namespace));
924 // Note: code ignores IsValueType annotation if derived type exists
925 if (baseContract.IsValueType)
926 baseContract.IsValueType = false;
928 ClassDataContract ancestorDataContract = baseContract;
929 while (ancestorDataContract != null)
931 DataContractDictionary knownDataContracts = ancestorDataContract.KnownDataContracts;
932 if (knownDataContracts == null)
934 knownDataContracts = new DataContractDictionary();
935 ancestorDataContract.KnownDataContracts = knownDataContracts;
937 knownDataContracts.Add(dataContract.StableName, dataContract);
938 ancestorDataContract = ancestorDataContract.BaseContract;
941 dataContract.BaseContract = baseContract;
944 void ImportTopLevelElement(XmlQualifiedName typeName)
946 XmlSchemaElement topLevelElement = SchemaHelper.GetSchemaElement(SchemaObjects, typeName);
947 // Top level element of same name is not required, but is validated if it is present
948 if (topLevelElement == null)
952 XmlQualifiedName elementTypeName = topLevelElement.SchemaTypeName;
953 if (elementTypeName.IsEmpty)
955 if (topLevelElement.SchemaType != null)
956 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.AnonymousTypeNotSupported, typeName.Name, typeName.Namespace));
958 elementTypeName = SchemaExporter.AnytypeQualifiedName;
960 if (elementTypeName != typeName)
961 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.TopLevelElementRepresentsDifferentType, topLevelElement.SchemaTypeName.Name, topLevelElement.SchemaTypeName.Namespace));
962 CheckIfElementUsesUnsupportedConstructs(typeName, topLevelElement);
966 void ImportClassMember(XmlSchemaElement element, ClassDataContract dataContract)
968 XmlQualifiedName typeName = dataContract.StableName;
970 if (element.MinOccurs > 1)
971 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ElementMinOccursMustBe, element.Name));
972 if (element.MaxOccurs != 1)
973 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ElementMaxOccursMustBe, element.Name));
975 DataContract memberTypeContract = null;
976 string memberName = element.Name;
977 bool memberIsRequired = (element.MinOccurs > 0);
978 bool memberIsNullable = element.IsNillable;
979 bool memberEmitDefaultValue;
982 XmlSchemaForm elementForm = (element.Form == XmlSchemaForm.None) ? SchemaHelper.GetSchemaWithType(SchemaObjects, schemaSet, typeName).ElementFormDefault : element.Form;
983 if (elementForm != XmlSchemaForm.Qualified)
984 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.FormMustBeQualified, element.Name));
985 CheckIfElementUsesUnsupportedConstructs(typeName, element);
987 if (element.SchemaTypeName.IsEmpty)
989 if (element.SchemaType != null)
990 memberTypeContract = ImportAnonymousElement(element, new XmlQualifiedName(String.Format(CultureInfo.InvariantCulture, "{0}.{1}Type", typeName.Name, element.Name), typeName.Namespace));
991 else if (!element.RefName.IsEmpty)
992 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ElementRefOnLocalElementNotSupported, element.RefName.Name, element.RefName.Namespace));
994 memberTypeContract = ImportType(SchemaExporter.AnytypeQualifiedName);
998 XmlQualifiedName memberTypeName = ImportActualType(element.Annotation, element.SchemaTypeName, typeName);
999 memberTypeContract = ImportType(memberTypeName);
1000 if (IsObjectContract(memberTypeContract))
1001 needToImportKnownTypesForObject = true;
1003 bool? emitDefaultValueFromAnnotation = ImportEmitDefaultValue(element.Annotation, typeName);
1004 if (!memberTypeContract.IsValueType && !memberIsNullable)
1006 if (emitDefaultValueFromAnnotation != null && emitDefaultValueFromAnnotation.Value)
1007 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidEmitDefaultAnnotation, memberName, typeName.Name, typeName.Namespace)));
1008 memberEmitDefaultValue = false;
1011 memberEmitDefaultValue = emitDefaultValueFromAnnotation != null ? emitDefaultValueFromAnnotation.Value : Globals.DefaultEmitDefaultValue;
1013 int prevMemberIndex = dataContract.Members.Count - 1;
1014 if (prevMemberIndex >= 0)
1016 DataMember prevMember = dataContract.Members[prevMemberIndex];
1017 if (prevMember.Order > Globals.DefaultOrder)
1018 memberOrder = dataContract.Members.Count;
1019 DataMember currentMember = new DataMember(memberTypeContract, memberName, memberIsNullable, memberIsRequired, memberEmitDefaultValue, memberOrder);
1020 int compare = ClassDataContract.DataMemberComparer.Singleton.Compare(prevMember, currentMember);
1022 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.CannotHaveDuplicateElementNames, memberName));
1023 else if (compare > 0)
1024 memberOrder = dataContract.Members.Count;
1026 DataMember dataMember = new DataMember(memberTypeContract, memberName, memberIsNullable, memberIsRequired, memberEmitDefaultValue, memberOrder);
1028 XmlQualifiedName surrogateDataAnnotationName = SchemaExporter.SurrogateDataAnnotationName;
1029 dataContractSet.SetSurrogateData(dataMember, ImportSurrogateData(ImportAnnotation(element.Annotation, surrogateDataAnnotationName), surrogateDataAnnotationName.Name, surrogateDataAnnotationName.Namespace));
1031 dataContract.Members.Add(dataMember);
1034 private bool? ImportEmitDefaultValue(XmlSchemaAnnotation annotation, XmlQualifiedName typeName)
1036 XmlElement defaultValueElement = ImportAnnotation(annotation, SchemaExporter.DefaultValueAnnotation);
1037 if (defaultValueElement == null)
1039 XmlNode emitDefaultValueAttribute = defaultValueElement.Attributes.GetNamedItem(Globals.EmitDefaultValueAttribute);
1040 string emitDefaultValueString = (emitDefaultValueAttribute == null) ? null : emitDefaultValueAttribute.Value;
1041 if (emitDefaultValueString == null)
1042 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.AnnotationAttributeNotFound, SchemaExporter.DefaultValueAnnotation.Name, typeName.Name, typeName.Namespace, Globals.EmitDefaultValueAttribute)));
1043 return XmlConvert.ToBoolean(emitDefaultValueString);
1046 internal static XmlQualifiedName ImportActualType(XmlSchemaAnnotation annotation, XmlQualifiedName defaultTypeName, XmlQualifiedName typeName)
1048 XmlElement actualTypeElement = ImportAnnotation(annotation, SchemaExporter.ActualTypeAnnotationName);
1049 if (actualTypeElement == null)
1050 return defaultTypeName;
1052 XmlNode nameAttribute = actualTypeElement.Attributes.GetNamedItem(Globals.ActualTypeNameAttribute);
1053 string name = (nameAttribute == null) ? null : nameAttribute.Value;
1055 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.AnnotationAttributeNotFound, SchemaExporter.ActualTypeAnnotationName.Name, typeName.Name, typeName.Namespace, Globals.ActualTypeNameAttribute)));
1056 XmlNode nsAttribute = actualTypeElement.Attributes.GetNamedItem(Globals.ActualTypeNamespaceAttribute);
1057 string ns = (nsAttribute == null) ? null : nsAttribute.Value;
1059 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.AnnotationAttributeNotFound, SchemaExporter.ActualTypeAnnotationName.Name, typeName.Name, typeName.Namespace, Globals.ActualTypeNamespaceAttribute)));
1060 return new XmlQualifiedName(name, ns);
1063 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on CollectionDataContract.",
1064 Safe = "Called during schema import/code generation.")]
1065 [SecuritySafeCritical]
1066 CollectionDataContract ImportCollection(XmlQualifiedName typeName, XmlSchemaSequence rootSequence, XmlSchemaObjectCollection attributes, XmlSchemaAnnotation annotation, bool isReference)
1068 CollectionDataContract dataContract = new CollectionDataContract(CollectionKind.Array);
1069 dataContract.StableName = typeName;
1070 AddDataContract(dataContract);
1072 dataContract.IsReference = isReference;
1074 // CheckIfCollection has already checked if sequence contains exactly one item with maxOccurs="unbounded" or maxOccurs > 1
1075 XmlSchemaElement element = (XmlSchemaElement)rootSequence.Items[0];
1077 dataContract.IsItemTypeNullable = element.IsNillable;
1078 dataContract.ItemName = element.Name;
1080 XmlSchemaForm elementForm = (element.Form == XmlSchemaForm.None) ? SchemaHelper.GetSchemaWithType(SchemaObjects, schemaSet, typeName).ElementFormDefault : element.Form;
1081 if (elementForm != XmlSchemaForm.Qualified)
1082 ThrowArrayTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ArrayItemFormMustBe, element.Name));
1083 CheckIfElementUsesUnsupportedConstructs(typeName, element);
1085 if (element.SchemaTypeName.IsEmpty)
1087 if (element.SchemaType != null)
1089 XmlQualifiedName shortName = new XmlQualifiedName(element.Name, typeName.Namespace);
1090 DataContract contract = dataContractSet[shortName];
1091 if (contract == null)
1093 dataContract.ItemContract = ImportAnonymousElement(element, shortName);
1097 XmlQualifiedName fullName = new XmlQualifiedName(String.Format(CultureInfo.InvariantCulture, "{0}.{1}Type", typeName.Name, element.Name), typeName.Namespace);
1098 dataContract.ItemContract = ImportAnonymousElement(element, fullName);
1101 else if (!element.RefName.IsEmpty)
1102 ThrowArrayTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.ElementRefOnLocalElementNotSupported, element.RefName.Name, element.RefName.Namespace));
1104 dataContract.ItemContract = ImportType(SchemaExporter.AnytypeQualifiedName);
1108 dataContract.ItemContract = ImportType(element.SchemaTypeName);
1111 if (IsDictionary(typeName, annotation))
1113 ClassDataContract keyValueContract = dataContract.ItemContract as ClassDataContract;
1114 DataMember key = null, value = null;
1115 if (keyValueContract == null || keyValueContract.Members == null || keyValueContract.Members.Count != 2
1116 || !(key = keyValueContract.Members[0]).IsRequired || !(value = keyValueContract.Members[1]).IsRequired)
1118 ThrowArrayTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.InvalidKeyValueType, element.Name));
1120 if (keyValueContract.Namespace != dataContract.Namespace)
1122 ThrowArrayTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.InvalidKeyValueTypeNamespace, element.Name, keyValueContract.Namespace));
1124 keyValueContract.IsValueType = true;
1125 dataContract.KeyName = key.Name;
1126 dataContract.ValueName = value.Name;
1127 if (element.SchemaType != null)
1129 dataContractSet.Remove(keyValueContract.StableName);
1131 GenericInfo genericInfo = new GenericInfo(DataContract.GetStableName(Globals.TypeOfKeyValue), Globals.TypeOfKeyValue.FullName);
1132 genericInfo.Add(GetGenericInfoForDataMember(key));
1133 genericInfo.Add(GetGenericInfoForDataMember(value));
1134 genericInfo.AddToLevel(0, 2);
1135 dataContract.ItemContract.StableName = new XmlQualifiedName(genericInfo.GetExpandedStableName().Name, typeName.Namespace);
1139 return dataContract;
1142 GenericInfo GetGenericInfoForDataMember(DataMember dataMember)
1144 GenericInfo genericInfo = null;
1145 if (dataMember.MemberTypeContract.IsValueType && dataMember.IsNullable)
1147 genericInfo = new GenericInfo(DataContract.GetStableName(Globals.TypeOfNullable), Globals.TypeOfNullable.FullName);
1148 genericInfo.Add(new GenericInfo(dataMember.MemberTypeContract.StableName, null));
1152 genericInfo = new GenericInfo(dataMember.MemberTypeContract.StableName, null);
1158 bool IsDictionary(XmlQualifiedName typeName, XmlSchemaAnnotation annotation)
1160 string isDictionaryInnerText = GetInnerText(typeName, ImportAnnotation(annotation, SchemaExporter.IsDictionaryAnnotationName));
1161 if (isDictionaryInnerText != null)
1165 return XmlConvert.ToBoolean(isDictionaryInnerText);
1167 catch (FormatException fe)
1169 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.IsDictionaryFormattedIncorrectly, isDictionaryInnerText, fe.Message));
1175 EnumDataContract ImportFlagsEnum(XmlQualifiedName typeName, XmlSchemaSimpleTypeList list, XmlSchemaAnnotation annotation)
1177 XmlSchemaSimpleType anonymousType = list.ItemType;
1178 if (anonymousType == null)
1179 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumListMustContainAnonymousType));
1181 XmlSchemaSimpleTypeContent content = anonymousType.Content;
1182 if (content is XmlSchemaSimpleTypeUnion)
1183 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumUnionInAnonymousTypeNotSupported));
1184 else if (content is XmlSchemaSimpleTypeList)
1185 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumListInAnonymousTypeNotSupported));
1186 else if (content is XmlSchemaSimpleTypeRestriction)
1188 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)content;
1189 if (CheckIfEnum(restriction))
1190 return ImportEnum(typeName, restriction, true /*isFlags*/, annotation);
1192 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumRestrictionInvalid));
1197 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on EnumDataContract.",
1198 Safe = "Called during schema import/code generation.")]
1199 [SecuritySafeCritical]
1200 EnumDataContract ImportEnum(XmlQualifiedName typeName, XmlSchemaSimpleTypeRestriction restriction, bool isFlags, XmlSchemaAnnotation annotation)
1202 EnumDataContract dataContract = new EnumDataContract();
1203 dataContract.StableName = typeName;
1204 dataContract.BaseContractName = ImportActualType(annotation, SchemaExporter.DefaultEnumBaseTypeName, typeName);
1205 dataContract.IsFlags = isFlags;
1206 AddDataContract(dataContract);
1208 // CheckIfEnum has already checked if baseType of restriction is string
1209 dataContract.Values = new List<long>();
1210 dataContract.Members = new List<DataMember>();
1211 foreach (XmlSchemaFacet facet in restriction.Facets)
1213 XmlSchemaEnumerationFacet enumFacet = facet as XmlSchemaEnumerationFacet;
1214 if (enumFacet == null)
1215 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumOnlyEnumerationFacetsSupported));
1216 if (enumFacet.Value == null)
1217 ThrowEnumTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.EnumEnumerationFacetsMustHaveValue));
1219 string valueInnerText = GetInnerText(typeName, ImportAnnotation(enumFacet.Annotation, SchemaExporter.EnumerationValueAnnotationName));
1220 if (valueInnerText == null)
1221 dataContract.Values.Add(SchemaExporter.GetDefaultEnumValue(isFlags, dataContract.Members.Count));
1223 dataContract.Values.Add(dataContract.GetEnumValueFromString(valueInnerText));
1224 DataMember dataMember = new DataMember(enumFacet.Value);
1225 dataContract.Members.Add(dataMember);
1227 return dataContract;
1230 DataContract ImportSimpleTypeRestriction(XmlQualifiedName typeName, XmlSchemaSimpleTypeRestriction restriction)
1232 DataContract dataContract = null;
1234 if (!restriction.BaseTypeName.IsEmpty)
1235 dataContract = ImportType(restriction.BaseTypeName);
1236 else if (restriction.BaseType != null)
1237 dataContract = ImportType(restriction.BaseType);
1239 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.SimpleTypeRestrictionDoesNotSpecifyBase));
1241 return dataContract;
1244 void ImportDataContractExtension(XmlSchemaType type, DataContract dataContract)
1246 if (type.Annotation == null || type.Annotation.Items == null)
1248 foreach (XmlSchemaObject schemaObject in type.Annotation.Items)
1250 XmlSchemaAppInfo appInfo = schemaObject as XmlSchemaAppInfo;
1251 if (appInfo == null)
1253 if (appInfo.Markup != null)
1255 foreach (XmlNode xmlNode in appInfo.Markup)
1257 XmlElement typeElement = xmlNode as XmlElement;
1258 XmlQualifiedName surrogateDataAnnotationName = SchemaExporter.SurrogateDataAnnotationName;
1259 if (typeElement != null && typeElement.NamespaceURI == surrogateDataAnnotationName.Namespace && typeElement.LocalName == surrogateDataAnnotationName.Name)
1261 object surrogateData = ImportSurrogateData(typeElement, surrogateDataAnnotationName.Name, surrogateDataAnnotationName.Namespace);
1262 dataContractSet.SetSurrogateData(dataContract, surrogateData);
1269 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on DataContract.",
1270 Safe = "Called during schema import/code generation.")]
1271 [SecuritySafeCritical]
1272 void ImportGenericInfo(XmlSchemaType type, DataContract dataContract)
1274 if (type.Annotation == null || type.Annotation.Items == null)
1276 foreach (XmlSchemaObject schemaObject in type.Annotation.Items)
1278 XmlSchemaAppInfo appInfo = schemaObject as XmlSchemaAppInfo;
1279 if (appInfo == null)
1281 if (appInfo.Markup != null)
1283 foreach (XmlNode xmlNode in appInfo.Markup)
1285 XmlElement typeElement = xmlNode as XmlElement;
1286 if (typeElement != null && typeElement.NamespaceURI == Globals.SerializationNamespace)
1288 if (typeElement.LocalName == Globals.GenericTypeLocalName)
1289 dataContract.GenericInfo = ImportGenericInfo(typeElement, type);
1296 GenericInfo ImportGenericInfo(XmlElement typeElement, XmlSchemaType type)
1298 XmlNode nameAttribute = typeElement.Attributes.GetNamedItem(Globals.GenericNameAttribute);
1299 string name = (nameAttribute == null) ? null : nameAttribute.Value;
1301 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationAttributeNotFound, type.Name, Globals.GenericNameAttribute)));
1302 XmlNode nsAttribute = typeElement.Attributes.GetNamedItem(Globals.GenericNamespaceAttribute);
1303 string ns = (nsAttribute == null) ? null : nsAttribute.Value;
1305 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationAttributeNotFound, type.Name, Globals.GenericNamespaceAttribute)));
1306 if (typeElement.ChildNodes.Count > 0) //Generic Type
1307 name = DataContract.EncodeLocalName(name);
1309 int currentLevel = 0;
1310 GenericInfo genInfo = new GenericInfo(new XmlQualifiedName(name, ns), type.Name);
1311 foreach (XmlNode childNode in typeElement.ChildNodes)
1313 XmlElement argumentElement = childNode as XmlElement;
1314 if (argumentElement == null)
1316 if (argumentElement.LocalName != Globals.GenericParameterLocalName ||
1317 argumentElement.NamespaceURI != Globals.SerializationNamespace)
1318 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationHasInvalidElement, argumentElement.LocalName, argumentElement.NamespaceURI, type.Name)));
1319 XmlNode nestedLevelAttribute = argumentElement.Attributes.GetNamedItem(Globals.GenericParameterNestedLevelAttribute);
1320 int argumentLevel = 0;
1321 if (nestedLevelAttribute != null)
1323 if (!Int32.TryParse(nestedLevelAttribute.Value, out argumentLevel))
1324 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationHasInvalidAttributeValue, argumentElement.LocalName, argumentElement.NamespaceURI, type.Name, nestedLevelAttribute.Value, nestedLevelAttribute.LocalName, Globals.TypeOfInt.Name)));
1326 if (argumentLevel < currentLevel)
1327 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationForNestedLevelMustBeIncreasing, argumentElement.LocalName, argumentElement.NamespaceURI, type.Name)));
1328 genInfo.Add(ImportGenericInfo(argumentElement, type));
1329 genInfo.AddToLevel(argumentLevel, 1);
1330 currentLevel = argumentLevel;
1333 XmlNode typeNestedLevelsAttribute = typeElement.Attributes.GetNamedItem(Globals.GenericParameterNestedLevelAttribute);
1334 if (typeNestedLevelsAttribute != null)
1336 int nestedLevels = 0;
1337 if (!Int32.TryParse(typeNestedLevelsAttribute.Value, out nestedLevels))
1338 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericAnnotationHasInvalidAttributeValue, typeElement.LocalName, typeElement.NamespaceURI, type.Name, typeNestedLevelsAttribute.Value, typeNestedLevelsAttribute.LocalName, Globals.TypeOfInt.Name)));
1339 if ((nestedLevels - 1) > currentLevel)
1340 genInfo.AddToLevel(nestedLevels - 1, 0);
1345 object ImportSurrogateData(XmlElement typeElement, string name, string ns)
1347 if (dataContractSet.DataContractSurrogate != null && typeElement != null)
1349 Collection<Type> knownTypes = new Collection<Type>();
1350 DataContractSurrogateCaller.GetKnownCustomDataTypes(dataContractSet.DataContractSurrogate, knownTypes);
1351 DataContractSerializer serializer = new DataContractSerializer(Globals.TypeOfObject, name, ns, knownTypes,
1352 Int32.MaxValue, false /*ignoreExtensionDataObject*/, true /*preserveObjectReferences*/, null /*dataContractSurrogate*/);
1353 return serializer.ReadObject(new XmlNodeReader(typeElement));
1358 void CheckComplexType(XmlQualifiedName typeName, XmlSchemaComplexType type)
1360 if (type.IsAbstract)
1361 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.AbstractTypeNotSupported));
1363 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.MixedContentNotSupported));
1366 void CheckIfElementUsesUnsupportedConstructs(XmlQualifiedName typeName, XmlSchemaElement element)
1368 if (element.IsAbstract)
1369 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.AbstractElementNotSupported, element.Name));
1370 if (element.DefaultValue != null)
1371 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.DefaultOnElementNotSupported, element.Name));
1372 if (element.FixedValue != null)
1373 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.FixedOnElementNotSupported, element.Name));
1374 if (!element.SubstitutionGroup.IsEmpty)
1375 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.SubstitutionGroupOnElementNotSupported, element.Name));
1378 void ImportAttributes(XmlQualifiedName typeName, XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, out bool isReference)
1380 if (anyAttribute != null)
1381 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.AnyAttributeNotSupported));
1383 isReference = false;
1384 if (attributes != null)
1386 bool foundId = false, foundRef = false;
1387 for (int i = 0; i < attributes.Count; i++)
1389 XmlSchemaObject o = attributes[i];
1390 if (o is XmlSchemaAttribute)
1392 XmlSchemaAttribute attribute = (XmlSchemaAttribute)o;
1393 if (attribute.Use == XmlSchemaUse.Prohibited)
1395 if (TryCheckIfAttribute(typeName, attribute, Globals.IdQualifiedName, ref foundId))
1397 if (TryCheckIfAttribute(typeName, attribute, Globals.RefQualifiedName, ref foundRef))
1399 if (attribute.RefName.IsEmpty || attribute.RefName.Namespace != Globals.SerializationNamespace || attribute.Use == XmlSchemaUse.Required)
1400 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.TypeShouldNotContainAttributes, Globals.SerializationNamespace));
1403 isReference = (foundId && foundRef);
1407 bool TryCheckIfAttribute(XmlQualifiedName typeName, XmlSchemaAttribute attribute, XmlQualifiedName refName, ref bool foundAttribute)
1409 if (attribute.RefName != refName)
1412 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.CannotHaveDuplicateAttributeNames, refName.Name));
1413 foundAttribute = true;
1417 void AddDataContract(DataContract dataContract)
1419 dataContractSet.Add(dataContract.StableName, dataContract);
1422 string GetInnerText(XmlQualifiedName typeName, XmlElement xmlElement)
1424 if (xmlElement != null)
1426 XmlNode child = xmlElement.FirstChild;
1427 while (child != null)
1429 if (child.NodeType == XmlNodeType.Element)
1430 ThrowTypeCannotBeImportedException(typeName.Name, typeName.Namespace, SR.GetString(SR.InvalidAnnotationExpectingText, xmlElement.LocalName, xmlElement.NamespaceURI, child.LocalName, child.NamespaceURI));
1431 child = child.NextSibling;
1433 return xmlElement.InnerText;
1438 static XmlElement ImportAnnotation(XmlSchemaAnnotation annotation, XmlQualifiedName annotationQualifiedName)
1440 if (annotation != null && annotation.Items != null && annotation.Items.Count > 0 && annotation.Items[0] is XmlSchemaAppInfo)
1442 XmlSchemaAppInfo appInfo = (XmlSchemaAppInfo)annotation.Items[0];
1443 XmlNode[] markup = appInfo.Markup;
1446 for (int i = 0; i < markup.Length; i++)
1448 XmlElement annotationElement = markup[i] as XmlElement;
1449 if (annotationElement != null && annotationElement.LocalName == annotationQualifiedName.Name && annotationElement.NamespaceURI == annotationQualifiedName.Namespace)
1450 return annotationElement;
1457 static void ThrowTypeCannotBeImportedException(string name, string ns, string message)
1459 ThrowTypeCannotBeImportedException(SR.GetString(SR.TypeCannotBeImported, name, ns, message));
1462 static void ThrowArrayTypeCannotBeImportedException(string name, string ns, string message)
1464 ThrowTypeCannotBeImportedException(SR.GetString(SR.ArrayTypeCannotBeImported, name, ns, message));
1467 static void ThrowEnumTypeCannotBeImportedException(string name, string ns, string message)
1469 ThrowTypeCannotBeImportedException(SR.GetString(SR.EnumTypeCannotBeImported, name, ns, message));
1472 static void ThrowISerializableTypeCannotBeImportedException(string name, string ns, string message)
1474 ThrowTypeCannotBeImportedException(SR.GetString(SR.ISerializableTypeCannotBeImported, name, ns, message));
1477 static void ThrowTypeCannotBeImportedException(string message)
1479 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeCannotBeImportedHowToFix, message)));