internal void SetContentModel(TextAccessor text, bool hasElements) { if (BaseMapping == null || BaseMapping.TypeDesc.IsRoot) { _hasSimpleContent = !hasElements && text != null && !text.Mapping.IsList; } else if (BaseMapping.HasSimpleContent) { if (text != null || hasElements) { // we can only extent a simleContent type with attributes throw new InvalidOperationException(SR.Format(SR.XmlIllegalSimpleContentExtension, TypeDesc.FullName, BaseMapping.TypeDesc.FullName)); } else { _hasSimpleContent = true; } } else { _hasSimpleContent = false; } if (!_hasSimpleContent && text != null && !text.Mapping.TypeDesc.CanBeTextValue && !(BaseMapping != null && !BaseMapping.TypeDesc.IsRoot && (text.Mapping.TypeDesc.IsEnum || text.Mapping.TypeDesc.IsPrimitive))) { throw new InvalidOperationException(SR.Format(SR.XmlIllegalTypedTextAttribute, TypeDesc.FullName, text.Name, text.Mapping.TypeDesc.FullName)); } }
private bool WriteMemberText(out object o, Member anyText) { MemberMapping anyTextMapping = anyText.Mapping; if ((Reader.NodeType == XmlNodeType.Text || Reader.NodeType == XmlNodeType.CDATA || Reader.NodeType == XmlNodeType.Whitespace || Reader.NodeType == XmlNodeType.SignificantWhitespace)) { TextAccessor text = anyTextMapping.Text; if (text.Mapping is SpecialMapping) { SpecialMapping special = (SpecialMapping)text.Mapping; if (special.TypeDesc.Kind == TypeKind.Node) { o = Document.CreateTextNode(ReadString()); } else { throw new InvalidOperationException(SR.Format(SR.XmlInternalError)); } } else { if (anyTextMapping.TypeDesc.IsArrayLike) { if (text.Mapping.TypeDesc.CollapseWhitespace) { o = CollapseWhitespace(ReadString()); } else { o = ReadString(); } } else { if (text.Mapping.TypeDesc == StringTypeDesc || text.Mapping.TypeDesc.FormatterName == "String") { o = ReadString(null, text.Mapping.TypeDesc.CollapseWhitespace); } else { o = WritePrimitive(text.Mapping, () => ReadString()); } } } return(true); } o = null; return(false); }
protected AccessorMapping(AccessorMapping mapping) : base(mapping) { this.typeDesc = mapping.typeDesc; this.attribute = mapping.attribute; this.elements = mapping.elements; this.sortedElements = mapping.sortedElements; this.text = mapping.text; this.choiceIdentifier = mapping.choiceIdentifier; this.xmlns = mapping.xmlns; this.ignore = mapping.ignore; }
protected AccessorMapping(AccessorMapping mapping) : base(mapping) { _typeDesc = mapping._typeDesc; _attribute = mapping._attribute; _elements = mapping._elements; _sortedElements = mapping._sortedElements; _text = mapping._text; _choiceIdentifier = mapping._choiceIdentifier; _xmlns = mapping._xmlns; _ignore = mapping._ignore; }
private bool WriteMemberText(out object o, Member anyText) { MemberMapping anyTextMapping = anyText.Mapping; if ((Reader.NodeType == XmlNodeType.Text || Reader.NodeType == XmlNodeType.CDATA || Reader.NodeType == XmlNodeType.Whitespace || Reader.NodeType == XmlNodeType.SignificantWhitespace)) { TextAccessor text = anyTextMapping.Text; if (text.Mapping is SpecialMapping) { // #10592: To Support text.Mapping being SpecialMapping throw new NotImplementedException("text.Mapping is SpecialMapping"); } else { if (anyTextMapping.TypeDesc.IsArrayLike) { if (text.Mapping.TypeDesc.CollapseWhitespace) { o = CollapseWhitespace(ReadString()); } else { o = ReadString(); } } else { if (text.Mapping.TypeDesc == StringTypeDesc || text.Mapping.TypeDesc.FormatterName == "String") { o = ReadString(null, text.Mapping.TypeDesc.CollapseWhitespace); } else { o = WritePrimitive(text.Mapping, () => ReadString()); } } } return(true); } o = null; return(false); }
private void WriteText(object o, TextAccessor text) { if (text.Mapping is PrimitiveMapping) { PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; string stringValue; if (text.Mapping is EnumMapping) { stringValue = WriteEnumMethod((EnumMapping)mapping, o); } else { if (!WritePrimitiveValue(mapping.TypeDesc, o, false, out stringValue)) { // #10593: Add More Tests for Serialization Code Debug.Assert(o is byte[]); } } if (o is byte[]) { WriteValue((byte[])o); } else { WriteValue(stringValue); } } else if (text.Mapping is SpecialMapping) { SpecialMapping mapping = (SpecialMapping)text.Mapping; switch (mapping.TypeDesc.Kind) { case TypeKind.Node: ((XmlNode)o).WriteTo(Writer); break; default: throw new InvalidOperationException(SR.Format(SR.XmlInternalError)); } } }
private void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, object o) { TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; var a = o as IEnumerable; // #10593: This assert may not be true. We need more tests for this method. Debug.Assert(a != null); var e = a.GetEnumerator(); if (e != null) { while (e.MoveNext()) { object ai = e.Current; WriteElements(ai, null /*choiceName + "i"*/, elements, text, choice, (string)null /*arrayName + "a"*/, true, true); } } }
internal void SetContentModel(TextAccessor text, bool hasElements) { if ((this.BaseMapping == null) || this.BaseMapping.TypeDesc.IsRoot) { this.hasSimpleContent = (!hasElements && (text != null)) && !text.Mapping.IsList; } else if (this.BaseMapping.HasSimpleContent) { if ((text != null) || hasElements) { throw new InvalidOperationException(Res.GetString("XmlIllegalSimpleContentExtension", new object[] { base.TypeDesc.FullName, this.BaseMapping.TypeDesc.FullName })); } this.hasSimpleContent = true; } else { this.hasSimpleContent = false; } if ((!this.hasSimpleContent && (text != null)) && !text.Mapping.TypeDesc.CanBeTextValue) { throw new InvalidOperationException(Res.GetString("XmlIllegalTypedTextAttribute", new object[] { base.TypeDesc.FullName, text.Name, text.Mapping.TypeDesc.FullName })); } }
void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) { TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; // The logic here is that // 1) Try to get the public "GetEnumerator" method. If the method exists, then use this method. // 2) If there's no public method exist, check if the type implemented IEnumerable<T>. If so, call the explicit method // 3) Otherwise, call the IEnumerable.GetEnumerator method if (arrayTypeDesc.IsEnumerable) { LocalBuilder eLoc = ilg.DeclareLocal(typeof(IEnumerator), "e"); MethodInfo getEnumeratorMethod = arrayTypeDesc.Type.GetMethod( "GetEnumerator", CodeGenerator.InstancePublicBindingFlags, null, CodeGenerator.EmptyTypeArray, null); if (getEnumeratorMethod != null && typeof(IEnumerator).IsAssignableFrom(getEnumeratorMethod.ReturnType)) { ilg.LoadAddress(ilg.GetVariable(arrayName)); } else { ilg.Load(ilg.GetVariable(arrayName)); Type typeIEnumerable = arrayTypeDesc.IsGenericInterface ? typeof(IEnumerable<>).MakeGenericType(arrayElementTypeDesc.Type) : typeof(IEnumerable); getEnumeratorMethod = typeIEnumerable.GetMethod( "GetEnumerator", CodeGenerator.InstanceBindingFlags, null, CodeGenerator.EmptyTypeArray, null); ilg.ConvertValue(arrayTypeDesc.Type, typeIEnumerable); } ilg.Call(getEnumeratorMethod); ilg.ConvertValue(getEnumeratorMethod.ReturnType, typeof(IEnumerator)); ilg.Stloc(eLoc); ilg.Ldloc(eLoc); ilg.Load(null); ilg.If(Cmp.NotEqualTo); ilg.WhileBegin(); string arrayNamePlusA = (arrayName).Replace(arrayTypeDesc.Name, "") + "a" + arrayElementTypeDesc.Name; string arrayNamePlusI = (arrayName).Replace(arrayTypeDesc.Name, "") + "i" + arrayElementTypeDesc.Name; WriteLocalDecl(arrayNamePlusI, "e.Current", arrayElementTypeDesc.Type); WriteElements(new SourceInfo(arrayNamePlusI, null, null, arrayElementTypeDesc.Type, ilg), choiceName + "i", elements, text, choice, arrayNamePlusA, true, true); ilg.WhileBeginCondition(); // while (e.MoveNext()) MethodInfo IEnumerator_MoveNext = typeof(IEnumerator).GetMethod( "MoveNext", CodeGenerator.InstanceBindingFlags, null, CodeGenerator.EmptyTypeArray, null ); ilg.Ldloc(eLoc); ilg.Call(IEnumerator_MoveNext); ilg.WhileEndCondition(); ilg.WhileEnd(); ilg.EndIf(); // if (e != null) } else { // Filter out type specific for index (code match reusing local). string iPlusArrayName = "i" + (arrayName).Replace(arrayTypeDesc.Name, ""); string arrayNamePlusA = (arrayName).Replace(arrayTypeDesc.Name, "") + "a" + arrayElementTypeDesc.Name; string arrayNamePlusI = (arrayName).Replace(arrayTypeDesc.Name, "") + "i" + arrayElementTypeDesc.Name; LocalBuilder localI = ilg.DeclareOrGetLocal(typeof(Int32), iPlusArrayName); ilg.For(localI, 0, ilg.GetLocal(arrayName)); int count = elements.Length + (text == null ? 0 : 1); if (count > 1) { WriteLocalDecl(arrayNamePlusI, RaCodeGen.GetStringForArrayMember(arrayName, iPlusArrayName, arrayTypeDesc), arrayElementTypeDesc.Type); if (choice != null) { WriteLocalDecl(choiceName + "i", RaCodeGen.GetStringForArrayMember(choiceName, iPlusArrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.Type); } WriteElements(new SourceInfo(arrayNamePlusI, null, null, arrayElementTypeDesc.Type, ilg), choiceName + "i", elements, text, choice, arrayNamePlusA, true, arrayElementTypeDesc.IsNullable); } else { WriteElements(new SourceInfo(RaCodeGen.GetStringForArrayMember(arrayName, iPlusArrayName, arrayTypeDesc), null, null, arrayElementTypeDesc.Type, ilg), null, elements, text, choice, arrayNamePlusA, true, arrayElementTypeDesc.IsNullable); } ilg.EndFor(); } }
private void WriteMember(object o, object choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, bool writeAccessors, XmlMapping parentMapping = null) { if (memberTypeDesc.IsArrayLike && !(elements.Length == 1 && elements[0].Mapping is ArrayMapping)) { WriteArray(o, choiceSource, elements, text, choice, memberTypeDesc); } else { WriteElements(o, choiceSource, elements, text, choice, "a", writeAccessors, memberTypeDesc.IsNullable, parentMapping); } }
/// <summary> /// Saves the content to a stream. /// </summary> /// <param name="stream"></param> public virtual void Save(Stream stream) { TextAccessor.Save(stream).Wait(); }
private void WriteElements(object o, object enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable, XmlMapping parentMapping = null) { if (elements.Length == 0 && text == null) return; if (elements.Length == 1 && text == null) { WriteElement(o, elements[0], arrayName, writeAccessors, parentMapping); } else { if (isNullable && choice == null && o == null) { return; } int anyCount = 0; var namedAnys = new List<ElementAccessor>(); ElementAccessor unnamedAny = null; // can only have one string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) namedAnys.Add(element); else if (unnamedAny == null) unnamedAny = element; } else if (choice != null) { if (o != null && o.GetType() == element.Mapping.TypeDesc.Type) { WriteElement(o, element, arrayName, writeAccessors); return; } } else { TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc; if (o.GetType() == td.Type) { WriteElement(o, element, arrayName, writeAccessors); return; } } } if (anyCount > 0) { var elem = o as XmlElement; if (elem != null) { foreach (ElementAccessor element in namedAnys) { if (element.Name == elem.Name && element.Namespace == elem.NamespaceURI) { WriteElement(elem, element, arrayName, writeAccessors); return; } } if (choice != null) { throw CreateChoiceIdentifierValueException(choice.Mapping.TypeDesc.FullName, choice.MemberName, elem.Name, elem.NamespaceURI); } if (unnamedAny != null) { WriteElement(elem, unnamedAny, arrayName, writeAccessors); return; } throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI); } } if (text != null) { bool useReflection = text.Mapping.TypeDesc.UseReflection; string fullTypeName = text.Mapping.TypeDesc.CSharpName; WriteText(o, text); return; } if (elements.Length > 0 && o != null) { throw CreateUnknownTypeException(o); } } }
private void WriteElements(SourceInfo source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) { if (elements.Length == 0 && text == null) return; if (elements.Length == 1 && text == null) { TypeDesc td = elements[0].IsUnbounded ? elements[0].Mapping.TypeDesc.CreateArrayTypeDesc() : elements[0].Mapping.TypeDesc; if (!elements[0].Any && !elements[0].Mapping.TypeDesc.IsOptionalValue) source = source.CastTo(td); WriteElement(source, elements[0], arrayName, writeAccessors); } else { bool doEndIf = false; if (isNullable && choice == null) { source.Load(typeof(object)); ilg.Load(null); ilg.If(Cmp.NotEqualTo); doEndIf = true; } int anyCount = 0; ArrayList namedAnys = new ArrayList(); ElementAccessor unnamedAny = null; // can only have one bool wroteFirstIf = false; string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) namedAnys.Add(element); else if (unnamedAny == null) unnamedAny = element; } else if (choice != null) { string fullTypeName = element.Mapping.TypeDesc.CSharpName; object enumValue; string enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue); if (wroteFirstIf) ilg.InitElseIf(); else { wroteFirstIf = true; ilg.InitIf(); } ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type); ilg.Load(enumValue); ilg.Ceq(); if (isNullable && !element.IsNullable) { Label labelFalse = ilg.DefineLabel(); Label labelEnd = ilg.DefineLabel(); ilg.Brfalse(labelFalse); source.Load(typeof(object)); ilg.Load(null); ilg.Cne(); ilg.Br_S(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); } ilg.AndIf(); WriteChoiceTypeCheck(source, fullTypeName, choice, enumFullName, element.Mapping.TypeDesc); SourceInfo castedSource = source; castedSource = source.CastTo(element.Mapping.TypeDesc); WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); } else { TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc; string fullTypeName = td.CSharpName; if (wroteFirstIf) ilg.InitElseIf(); else { wroteFirstIf = true; ilg.InitIf(); } WriteInstanceOf(source, td.Type); // WriteInstanceOf leave bool on the stack ilg.AndIf(); SourceInfo castedSource = source; castedSource = source.CastTo(td); WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); } } if (wroteFirstIf) { if (anyCount > 0) { // See "else " below if (elements.Length - anyCount > 0) { // NOOP } else ilg.EndIf(); } } if (anyCount > 0) { if (elements.Length - anyCount > 0) ilg.InitElseIf(); else ilg.InitIf(); string fullTypeName = typeof(XmlElement).FullName; source.Load(typeof(object)); ilg.IsInst(typeof(XmlElement)); ilg.Load(null); ilg.Cne(); ilg.AndIf(); LocalBuilder elemLoc = ilg.DeclareLocal(typeof(XmlElement), "elem"); source.Load(typeof(XmlElement)); ilg.Stloc(elemLoc); int c = 0; foreach (ElementAccessor element in namedAnys) { if (c++ > 0) ilg.InitElseIf(); else ilg.InitIf(); string enumFullName = null; Label labelEnd, labelFalse; if (choice != null) { object enumValue; enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue); labelFalse = ilg.DefineLabel(); labelEnd = ilg.DefineLabel(); ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type); ilg.Load(enumValue); ilg.Bne(labelFalse); if (isNullable && !element.IsNullable) { source.Load(typeof(object)); ilg.Load(null); ilg.Cne(); } else { ilg.Ldc(true); } ilg.Br(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); ilg.AndIf(); } labelFalse = ilg.DefineLabel(); labelEnd = ilg.DefineLabel(); MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod( "get_Name", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod( "get_NamespaceURI", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_Name); ilg.Ldstr(GetCSharpString(element.Name)); MethodInfo String_op_Equality = typeof(string).GetMethod( "op_Equality", CodeGenerator.StaticBindingFlags, new Type[] { typeof(string), typeof(string) } ); ilg.Call(String_op_Equality); ilg.Brfalse(labelFalse); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Ldstr(GetCSharpString(element.Namespace)); ilg.Call(String_op_Equality); ilg.Br(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); if (choice != null) ilg.If(); else ilg.AndIf(); WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), element, arrayName, writeAccessors); if (choice != null) { ilg.Else(); MethodInfo XmlSerializationWriter_CreateChoiceIdentifierValueException = typeof(XmlSerializationWriter).GetMethod( "CreateChoiceIdentifierValueException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(enumFullName)); ilg.Ldstr(GetCSharpString(choice.MemberName)); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_Name); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Call(XmlSerializationWriter_CreateChoiceIdentifierValueException); ilg.Throw(); ilg.EndIf(); } } if (c > 0) { ilg.Else(); } if (unnamedAny != null) { WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), unnamedAny, arrayName, writeAccessors); } else { MethodInfo XmlSerializationWriter_CreateUnknownAnyElementException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownAnyElementException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldloc(elemLoc); MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod( "get_Name", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod( "get_NamespaceURI", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Call(XmlNode_get_Name); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Call(XmlSerializationWriter_CreateUnknownAnyElementException); ilg.Throw(); } if (c > 0) { ilg.EndIf(); } } if (text != null) { string fullTypeName = text.Mapping.TypeDesc.CSharpName; if (elements.Length > 0) { ilg.InitElseIf(); WriteInstanceOf(source, text.Mapping.TypeDesc.Type); ilg.AndIf(); SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc); WriteText(castedSource, text); } else { SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc); WriteText(castedSource, text); } } if (elements.Length > 0) { if (isNullable) { ilg.InitElseIf(); source.Load(null); ilg.Load(null); ilg.AndIf(Cmp.NotEqualTo); } else { ilg.Else(); } MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownTypeException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(Object) }); ilg.Ldarg(0); source.Load(typeof(object)); ilg.Call(XmlSerializationWriter_CreateUnknownTypeException); ilg.Throw(); ilg.EndIf(); } // See ilg.If() cond above if (doEndIf) // if (isNullable && choice == null) ilg.EndIf(); } }
private void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) { TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; if (arrayTypeDesc.IsEnumerable) { LocalBuilder eLoc = ilg.DeclareLocal(typeof(IEnumerator), "e"); ilg.LoadAddress(ilg.GetVariable(arrayName)); MethodInfo getEnumeratorMethod; if (arrayTypeDesc.IsPrivateImplementation) { Type typeIEnumerable = typeof(IEnumerable); getEnumeratorMethod = typeIEnumerable.GetMethod( "GetEnumerator", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>()); ilg.ConvertValue(arrayTypeDesc.Type, typeIEnumerable); } else if (arrayTypeDesc.IsGenericInterface) { Type typeIEnumerable = typeof(IEnumerable<>).MakeGenericType(arrayElementTypeDesc.Type); getEnumeratorMethod = typeIEnumerable.GetMethod( "GetEnumerator", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>()); ilg.ConvertValue(arrayTypeDesc.Type, typeIEnumerable); } else { getEnumeratorMethod = arrayTypeDesc.Type.GetMethod( "GetEnumerator", Array.Empty<Type>()); } ilg.Call(getEnumeratorMethod); ilg.ConvertValue(getEnumeratorMethod.ReturnType, typeof(IEnumerator)); ilg.Stloc(eLoc); ilg.Ldloc(eLoc); ilg.Load(null); ilg.If(Cmp.NotEqualTo); ilg.WhileBegin(); string arrayNamePlusA = (arrayName).Replace(arrayTypeDesc.Name, "") + "a" + arrayElementTypeDesc.Name; string arrayNamePlusI = (arrayName).Replace(arrayTypeDesc.Name, "") + "i" + arrayElementTypeDesc.Name; WriteLocalDecl(arrayNamePlusI, "e.Current", arrayElementTypeDesc.Type); WriteElements(new SourceInfo(arrayNamePlusI, null, null, arrayElementTypeDesc.Type, ilg), choiceName + "i", elements, text, choice, arrayNamePlusA, true, true); ilg.WhileBeginCondition(); // while (e.MoveNext()) MethodInfo IEnumerator_MoveNext = typeof(IEnumerator).GetMethod( "MoveNext", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>()); ilg.Ldloc(eLoc); ilg.Call(IEnumerator_MoveNext); ilg.WhileEndCondition(); ilg.WhileEnd(); ilg.EndIf(); // if (e != null) } else { // Filter out type specific for index (code match reusing local). string iPlusArrayName = "i" + (arrayName).Replace(arrayTypeDesc.Name, ""); string arrayNamePlusA = (arrayName).Replace(arrayTypeDesc.Name, "") + "a" + arrayElementTypeDesc.Name; string arrayNamePlusI = (arrayName).Replace(arrayTypeDesc.Name, "") + "i" + arrayElementTypeDesc.Name; LocalBuilder localI = ilg.DeclareOrGetLocal(typeof(Int32), iPlusArrayName); ilg.For(localI, 0, ilg.GetLocal(arrayName)); int count = elements.Length + (text == null ? 0 : 1); if (count > 1) { WriteLocalDecl(arrayNamePlusI, RaCodeGen.GetStringForArrayMember(arrayName, iPlusArrayName, arrayTypeDesc), arrayElementTypeDesc.Type); if (choice != null) { WriteLocalDecl(choiceName + "i", RaCodeGen.GetStringForArrayMember(choiceName, iPlusArrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.Type); } WriteElements(new SourceInfo(arrayNamePlusI, null, null, arrayElementTypeDesc.Type, ilg), choiceName + "i", elements, text, choice, arrayNamePlusA, true, arrayElementTypeDesc.IsNullable); } else { WriteElements(new SourceInfo(RaCodeGen.GetStringForArrayMember(arrayName, iPlusArrayName, arrayTypeDesc), null, null, arrayElementTypeDesc.Type, ilg), null, elements, text, choice, arrayNamePlusA, true, arrayElementTypeDesc.IsNullable); } ilg.EndFor(); } }
private void WriteArray(SourceInfo source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) { if (elements.Length == 0 && text == null) return; string arrayTypeName = arrayTypeDesc.CSharpName; string aName = "a" + arrayTypeDesc.Name; WriteArrayLocalDecl(arrayTypeName, aName, source, arrayTypeDesc); LocalBuilder aLoc = ilg.GetLocal(aName); if (arrayTypeDesc.IsNullable) { ilg.Ldloc(aLoc); ilg.Load(null); ilg.If(Cmp.NotEqualTo); } string cName = null; if (choice != null) { string choiceFullName = choice.Mapping.TypeDesc.CSharpName; SourceInfo choiceSourceInfo = new SourceInfo(choiceSource, null, choice.MemberInfo, null, ilg); cName = "c" + choice.Mapping.TypeDesc.Name; WriteArrayLocalDecl(choiceFullName + "[]", cName, choiceSourceInfo, choice.Mapping.TypeDesc); // write check for the choice identifier array Label labelEnd = ilg.DefineLabel(); Label labelTrue = ilg.DefineLabel(); LocalBuilder cLoc = ilg.GetLocal(cName); ilg.Ldloc(cLoc); ilg.Load(null); ilg.Beq(labelTrue); ilg.Ldloc(cLoc); ilg.Ldlen(); ilg.Ldloc(aLoc); ilg.Ldlen(); ilg.Clt(); ilg.Br(labelEnd); ilg.MarkLabel(labelTrue); ilg.Ldc(true); ilg.MarkLabel(labelEnd); ilg.If(); MethodInfo XmlSerializationWriter_CreateInvalidChoiceIdentifierValueException = typeof(XmlSerializationWriter).GetMethod( "CreateInvalidChoiceIdentifierValueException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(choice.Mapping.TypeDesc.FullName)); ilg.Ldstr(GetCSharpString(choice.MemberName)); ilg.Call(XmlSerializationWriter_CreateInvalidChoiceIdentifierValueException); ilg.Throw(); ilg.EndIf(); } WriteArrayItems(elements, text, choice, arrayTypeDesc, aName, cName); if (arrayTypeDesc.IsNullable) { ilg.EndIf(); } }
private void WriteMember(SourceInfo source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, bool writeAccessors) { if (memberTypeDesc.IsArrayLike && !(elements.Length == 1 && elements[0].Mapping is ArrayMapping)) WriteArray(source, choiceSource, elements, text, choice, memberTypeDesc); else // NOTE: Use different variable name to work around reuse same variable name in different scope WriteElements(source, choiceSource, elements, text, choice, "a" + memberTypeDesc.Name, writeAccessors, memberTypeDesc.IsNullable); }
private MemberMapping ImportAnyMember(XmlSchemaAny any, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, ref bool mixed, ref bool needExplicitOrder, bool allowDuplicates) { ElementAccessor[] accessors = ImportAny(any, !mixed, ns); AddScopeElements(elementsScope, accessors, ref needExplicitOrder, allowDuplicates); MemberMapping member = new MemberMapping(); member.Elements = accessors; member.Name = membersScope.MakeRightCase("Any"); member.Name = membersScope.AddUnique(member.Name, member); members.Add(member.Name, member); member.TypeDesc = ((TypeMapping)accessors[0].Mapping).TypeDesc; bool repeats = any.IsMultipleOccurrence; if (mixed) { SpecialMapping textMapping = new SpecialMapping(); textMapping.TypeDesc = Scope.GetTypeDesc(typeof(XmlNode)); textMapping.TypeName = textMapping.TypeDesc.Name; member.TypeDesc = textMapping.TypeDesc; TextAccessor text = new TextAccessor(); text.Mapping = textMapping; member.Text = text; repeats = true; mixed = false; } if (repeats) { member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc(); } return member; }
void WriteElements(string source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) { if (elements.Length == 0 && text == null) return; if (elements.Length == 1 && text == null) { TypeDesc td = elements[0].IsUnbounded ? elements[0].Mapping.TypeDesc.CreateArrayTypeDesc() : elements[0].Mapping.TypeDesc; if (!elements[0].Any && !elements[0].Mapping.TypeDesc.UseReflection && !elements[0].Mapping.TypeDesc.IsOptionalValue) source = "(("+td.CSharpName+")"+ source+")"; WriteElement(source, elements[0], arrayName, writeAccessors); } else { if (isNullable && choice == null) { Writer.Write("if ((object)("); Writer.Write(source); Writer.Write(") != null)"); } Writer.WriteLine("{"); Writer.Indent++; int anyCount = 0; ArrayList namedAnys = new ArrayList(); ElementAccessor unnamedAny = null; // can only have one bool wroteFirstIf = false; string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) namedAnys.Add(element); else if (unnamedAny == null) unnamedAny = element; } else if (choice != null) { bool useReflection = element.Mapping.TypeDesc.UseReflection; string fullTypeName = element.Mapping.TypeDesc.CSharpName; bool enumUseReflection = choice.Mapping.TypeDesc.UseReflection; string enumFullName = (enumUseReflection?"":enumTypeName + ".@") + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, enumUseReflection); if (wroteFirstIf) Writer.Write("else "); else wroteFirstIf = true; Writer.Write("if ("); Writer.Write(enumUseReflection?RaCodeGen.GetStringForEnumLongValue(enumSource, enumUseReflection):enumSource); Writer.Write(" == "); Writer.Write(enumFullName); if (isNullable && !element.IsNullable) { Writer.Write(" && ((object)("); Writer.Write(source); Writer.Write(") != null)"); } Writer.WriteLine(") {"); Writer.Indent++; WriteChoiceTypeCheck(source, fullTypeName, useReflection, choice, enumFullName, element.Mapping.TypeDesc); string castedSource = source; if (!useReflection) castedSource = "(("+fullTypeName+")"+ source+")"; WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); Writer.Indent--; Writer.WriteLine("}"); } else { bool useReflection = element.Mapping.TypeDesc.UseReflection; TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc; string fullTypeName = td.CSharpName; if (wroteFirstIf) Writer.Write("else "); else wroteFirstIf = true; Writer.Write("if ("); WriteInstanceOf(source, fullTypeName, useReflection); Writer.WriteLine(") {"); Writer.Indent++; string castedSource = source; if (!useReflection) castedSource = "(("+fullTypeName+")"+ source+")"; WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); Writer.Indent--; Writer.WriteLine("}"); } } if (anyCount > 0) { if (elements.Length - anyCount > 0) Writer.Write("else "); string fullTypeName = typeof(XmlElement).FullName; Writer.Write("if ("); Writer.Write(source); Writer.Write(" is "); Writer.Write(fullTypeName); Writer.WriteLine(") {"); Writer.Indent++; Writer.Write(fullTypeName); Writer.Write(" elem = ("); Writer.Write(fullTypeName); Writer.Write(")"); Writer.Write(source); Writer.WriteLine(";"); int c = 0; foreach (ElementAccessor element in namedAnys) { if (c++ > 0) Writer.Write("else "); string enumFullName = null; bool useReflection = element.Mapping.TypeDesc.UseReflection; if (choice != null) { bool enumUseReflection = choice.Mapping.TypeDesc.UseReflection; enumFullName = (enumUseReflection?"":enumTypeName + ".@") + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, enumUseReflection); Writer.Write("if ("); Writer.Write(enumUseReflection?RaCodeGen.GetStringForEnumLongValue(enumSource, enumUseReflection):enumSource); Writer.Write(" == "); Writer.Write(enumFullName); if (isNullable && !element.IsNullable) { Writer.Write(" && ((object)("); Writer.Write(source); Writer.Write(") != null)"); } Writer.WriteLine(") {"); Writer.Indent++; } Writer.Write("if (elem.Name == "); WriteQuotedCSharpString(element.Name); Writer.Write(" && elem.NamespaceURI == "); WriteQuotedCSharpString(element.Namespace); Writer.WriteLine(") {"); Writer.Indent++; WriteElement("elem", element, arrayName, writeAccessors); if (choice != null) { Writer.Indent--; Writer.WriteLine("}"); Writer.WriteLine("else {"); Writer.Indent++; Writer.WriteLine("// throw Value '{0}' of the choice identifier '{1}' does not match element '{2}' from namespace '{3}'."); Writer.Write("throw CreateChoiceIdentifierValueException("); WriteQuotedCSharpString(enumFullName); Writer.Write(", "); WriteQuotedCSharpString(choice.MemberName); Writer.WriteLine(", elem.Name, elem.NamespaceURI);"); Writer.Indent--; Writer.WriteLine("}"); } Writer.Indent--; Writer.WriteLine("}"); } if (c > 0) { Writer.WriteLine("else {"); Writer.Indent++; } if (unnamedAny != null) { WriteElement("elem", unnamedAny, arrayName, writeAccessors); } else { Writer.WriteLine("throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI);"); } if (c > 0) { Writer.Indent--; Writer.WriteLine("}"); } Writer.Indent--; Writer.WriteLine("}"); } if (text != null) { bool useReflection = text.Mapping.TypeDesc.UseReflection; string fullTypeName = text.Mapping.TypeDesc.CSharpName; if (elements.Length > 0) { Writer.Write("else "); Writer.Write("if ("); WriteInstanceOf(source, fullTypeName, useReflection); Writer.WriteLine(") {"); Writer.Indent++; string castedSource = source; if (!useReflection) castedSource = "(("+fullTypeName+")"+ source+")"; WriteText(castedSource, text); Writer.Indent--; Writer.WriteLine("}"); } else { string castedSource = source; if (!useReflection) castedSource = "(("+fullTypeName+")"+ source+")"; WriteText(castedSource, text); } } if (elements.Length > 0) { Writer.Write("else "); if (isNullable) { Writer.Write(" if ((object)("); Writer.Write(source); Writer.Write(") != null)"); } Writer.WriteLine("{"); Writer.Indent++; Writer.Write("throw CreateUnknownTypeException("); Writer.Write(source); Writer.WriteLine(");"); Writer.Indent--; Writer.WriteLine("}"); } Writer.Indent--; Writer.WriteLine("}"); } }
private void WriteText(SourceInfo source, TextAccessor text) { if (text.Mapping is PrimitiveMapping) { PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; Type argType; ilg.Ldarg(0); if (text.Mapping is EnumMapping) { WriteEnumValue((EnumMapping)text.Mapping, source, out argType); } else { WritePrimitiveValue(mapping.TypeDesc, source, out argType); } MethodInfo XmlSerializationWriter_WriteValue = typeof(XmlSerializationWriter).GetMethod( "WriteValue", CodeGenerator.InstanceBindingFlags, new Type[] { argType } ); ilg.Call(XmlSerializationWriter_WriteValue); } else if (text.Mapping is SpecialMapping) { SpecialMapping mapping = (SpecialMapping)text.Mapping; switch (mapping.TypeDesc.Kind) { case TypeKind.Node: MethodInfo WriteTo = source.Type.GetMethod( "WriteTo", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(XmlWriter) } ); MethodInfo XmlSerializationWriter_get_Writer = typeof(XmlSerializationWriter).GetMethod( "get_Writer", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); source.Load(source.Type); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_get_Writer); ilg.Call(WriteTo); break; default: throw new InvalidOperationException(SR.XmlInternalError); } } }
void ImportTextMember(CodeIdentifiers members, XmlQualifiedName simpleContentType) { TypeMapping mapping; bool isMixed = false; if (simpleContentType != null) { mapping = ImportType(simpleContentType, typeof(TypeMapping), null); if (!(mapping is PrimitiveMapping || mapping.TypeDesc.CanBeTextValue)) { return; } } else { // this is a case of the mixed content type, just generate string typeDesc isMixed = true; mapping = new PrimitiveMapping(); mapping.TypeDesc = scope.GetTypeDesc(typeof(string)); mapping.TypeName = mapping.TypeDesc.DataType.Name; } TextAccessor accessor = new TextAccessor(); accessor.Mapping = mapping; MemberMapping member = new MemberMapping(); member.Elements = new ElementAccessor[0]; member.Text = accessor; if (isMixed) { // just generate code for the standard mixed case (string[] text) member.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc(); member.Name = members.MakeRightCase("Text"); } else { // import mapping for the simpleContent PrimitiveMapping pm = (PrimitiveMapping)accessor.Mapping; if (pm.IsList) { member.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc(); member.Name = members.MakeRightCase("Text"); } else { member.TypeDesc = accessor.Mapping.TypeDesc; member.Name = members.MakeRightCase("Value"); } } member.Name = members.AddUnique(member.Name, member); }
void ImportAnyMember(XmlSchemaAny any, string identifier, CodeIdentifiers members, string ns, bool mixed) { ElementAccessor accessor = ImportAny(any, !mixed); accessor.Name = identifier; accessor.Namespace = ns; MemberMapping member = new MemberMapping(); member.Elements = new ElementAccessor[] { accessor }; member.Name = members.MakeRightCase("Any"); member.Name = members.AddUnique(member.Name, member); member.TypeDesc = ((TypeMapping)accessor.Mapping).TypeDesc; bool repeats = any.IsMultipleOccurrence; if (mixed) { SpecialMapping textMapping = new SpecialMapping(); textMapping.TypeDesc = scope.GetTypeDesc(typeof(XmlNode)); textMapping.TypeName = textMapping.TypeDesc.Name; member.TypeDesc = textMapping.TypeDesc; TextAccessor text = new TextAccessor(); text.Mapping = textMapping; member.Text = text; repeats = true; } if (repeats) { member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc(); } }
private MemberMapping ImportAnyMember(XmlSchemaAny any, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, ref bool mixed, ref bool needExplicitOrder, bool allowDuplicates) { MemberMapping mapping; ElementAccessor[] elements = this.ImportAny(any, !mixed, ns); this.AddScopeElements(elementsScope, elements, ref needExplicitOrder, allowDuplicates); mapping = new MemberMapping { Elements = elements, Name = membersScope.MakeRightCase("Any"), Name = membersScope.AddUnique(mapping.Name, mapping) }; members.Add(mapping.Name, mapping); mapping.TypeDesc = elements[0].Mapping.TypeDesc; bool isMultipleOccurrence = any.IsMultipleOccurrence; if (mixed) { SpecialMapping mapping2; mapping2 = new SpecialMapping { TypeDesc = base.Scope.GetTypeDesc(typeof(XmlNode)), TypeName = mapping2.TypeDesc.Name }; mapping.TypeDesc = mapping2.TypeDesc; TextAccessor accessor = new TextAccessor { Mapping = mapping2 }; mapping.Text = accessor; isMultipleOccurrence = true; mixed = false; } if (isMultipleOccurrence) { mapping.TypeDesc = mapping.TypeDesc.CreateArrayTypeDesc(); } return mapping; }
private void WriteArray(object o, object choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) { if (elements.Length == 0 && text == null) { return; } if (arrayTypeDesc.IsNullable && o == null) { return; } if (choice != null) { if (choiceSource == null || ((Array)choiceSource).Length < ((Array)o).Length) { throw CreateInvalidChoiceIdentifierValueException(choice.Mapping.TypeDesc.FullName, choice.MemberName); } } WriteArrayItems(elements, text, choice, arrayTypeDesc, o); }
private void ImportTextMember(CodeIdentifiers members, CodeIdentifiers membersScope, XmlQualifiedName simpleContentType) { TypeMapping defaultMapping; bool flag = false; if (simpleContentType != null) { defaultMapping = this.ImportType(simpleContentType, typeof(TypeMapping), null, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue, false); if (!(defaultMapping is PrimitiveMapping) && !defaultMapping.TypeDesc.CanBeTextValue) { return; } } else { flag = true; defaultMapping = this.GetDefaultMapping(TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue); } TextAccessor accessor = new TextAccessor { Mapping = defaultMapping }; MemberMapping mapping2 = new MemberMapping { Elements = new ElementAccessor[0], Text = accessor }; if (flag) { mapping2.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc(); mapping2.Name = members.MakeRightCase("Text"); } else { PrimitiveMapping mapping = (PrimitiveMapping) accessor.Mapping; if (mapping.IsList) { mapping2.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc(); mapping2.Name = members.MakeRightCase("Text"); } else { mapping2.TypeDesc = accessor.Mapping.TypeDesc; mapping2.Name = members.MakeRightCase("Value"); } } mapping2.Name = membersScope.AddUnique(mapping2.Name, mapping2); members.Add(mapping2.Name, mapping2); }
private void WriteElements(object o, object enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable, XmlMapping parentMapping = null) { if (elements.Length == 0 && text == null) { return; } if (elements.Length == 1 && text == null) { WriteElement(o, elements[0], arrayName, writeAccessors, parentMapping); } else { if (isNullable && choice == null && o == null) { return; } int anyCount = 0; var namedAnys = new List <ElementAccessor>(); ElementAccessor unnamedAny = null; // can only have one string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) { namedAnys.Add(element); } else if (unnamedAny == null) { unnamedAny = element; } } else if (choice != null) { if (o != null && o.GetType() == element.Mapping.TypeDesc.Type) { WriteElement(o, element, arrayName, writeAccessors); return; } } else { TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc; if (o.GetType() == td.Type) { WriteElement(o, element, arrayName, writeAccessors); return; } } } if (anyCount > 0) { var elem = o as XmlElement; if (elem != null) { foreach (ElementAccessor element in namedAnys) { if (element.Name == elem.Name && element.Namespace == elem.NamespaceURI) { WriteElement(elem, element, arrayName, writeAccessors); return; } } if (choice != null) { throw CreateChoiceIdentifierValueException(choice.Mapping.TypeDesc.FullName, choice.MemberName, elem.Name, elem.NamespaceURI); } if (unnamedAny != null) { WriteElement(elem, unnamedAny, arrayName, writeAccessors); return; } throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI); } } if (text != null) { bool useReflection = text.Mapping.TypeDesc.UseReflection; string fullTypeName = text.Mapping.TypeDesc.CSharpName; WriteText(o, text); return; } if (elements.Length > 0 && o != null) { throw CreateUnknownTypeException(o); } } }
void WriteMember(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, bool writeAccessors) { if (memberTypeDesc.IsArrayLike && !(elements.Length == 1 && elements[0].Mapping is ArrayMapping)) WriteArray(source, choiceSource, elements, text, choice, memberTypeDesc); else WriteElements(source, choiceSource, elements, text, choice, "a", writeAccessors, memberTypeDesc.IsNullable); }
internal void SetContentModel(TextAccessor text, bool hasElements) { if (BaseMapping == null || BaseMapping.TypeDesc.IsRoot) { _hasSimpleContent = !hasElements && text != null && !text.Mapping.IsList; } else if (BaseMapping.HasSimpleContent) { if (text != null || hasElements) { // we can only extent a simleContent type with attributes throw new InvalidOperationException(SR.Format(SR.XmlIllegalSimpleContentExtension, TypeDesc.FullName, BaseMapping.TypeDesc.FullName)); } else { _hasSimpleContent = true; } } else { _hasSimpleContent = false; } if (!_hasSimpleContent && text != null && !text.Mapping.TypeDesc.CanBeTextValue) { throw new InvalidOperationException(SR.Format(SR.XmlIllegalTypedTextAttribute, TypeDesc.FullName, text.Name, text.Mapping.TypeDesc.FullName)); } }
void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) { TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; if (arrayTypeDesc.IsEnumerable) { Writer.Write(typeof(IEnumerator).FullName); Writer.Write(" e = "); if (arrayTypeDesc.IsPrivateImplementation) { Writer.Write("(("); Writer.Write(typeof(IEnumerable).FullName); Writer.Write(")"); Writer.Write(arrayName); Writer.WriteLine(").GetEnumerator();"); } else if(arrayTypeDesc.IsGenericInterface) { if (arrayTypeDesc.UseReflection) { // we use wildcard method name for generic GetEnumerator method, so we cannot use GetStringForMethodInvoke call here Writer.Write("("); Writer.Write(typeof(IEnumerator).FullName); Writer.Write(")"); Writer.Write(RaCodeGen.GetReflectionVariable(arrayTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*")); Writer.Write(".Invoke("); Writer.Write(arrayName); Writer.WriteLine(", new object[0]);"); } else { Writer.Write("((System.Collections.Generic.IEnumerable<"); Writer.Write(arrayElementTypeDesc.CSharpName); Writer.Write(">)"); Writer.Write(arrayName); Writer.WriteLine(").GetEnumerator();"); } } else { if (arrayTypeDesc.UseReflection) { Writer.Write("("); Writer.Write(typeof(IEnumerator).FullName); Writer.Write(")"); } Writer.Write(RaCodeGen.GetStringForMethodInvoke(arrayName, arrayTypeDesc.CSharpName, "GetEnumerator", arrayTypeDesc.UseReflection)); Writer.WriteLine(";"); } Writer.WriteLine("if (e != null)"); Writer.WriteLine("while (e.MoveNext()) {"); Writer.Indent++; string arrayTypeFullName = arrayElementTypeDesc.CSharpName; WriteLocalDecl(arrayTypeFullName, arrayName+"i", "e.Current", arrayElementTypeDesc.UseReflection); WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, true); } else { Writer.Write("for (int i"); Writer.Write(arrayName); Writer.Write(" = 0; i"); Writer.Write(arrayName); Writer.Write(" < "); if (arrayTypeDesc.IsArray) { Writer.Write(arrayName); Writer.Write(".Length"); } else { Writer.Write("(("); Writer.Write(typeof(ICollection).FullName); Writer.Write(")"); Writer.Write(arrayName); Writer.Write(").Count"); } Writer.Write("; i"); Writer.Write(arrayName); Writer.WriteLine("++) {"); Writer.Indent++; int count = elements.Length + (text == null ? 0 : 1); if (count > 1) { string arrayTypeFullName = arrayElementTypeDesc.CSharpName; WriteLocalDecl(arrayTypeFullName, arrayName+"i", RaCodeGen.GetStringForArrayMember(arrayName, "i"+arrayName, arrayTypeDesc), arrayElementTypeDesc.UseReflection); if (choice != null) { string choiceFullName = choice.Mapping.TypeDesc.CSharpName; WriteLocalDecl(choiceFullName, choiceName+"i", RaCodeGen.GetStringForArrayMember(choiceName, "i"+arrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.UseReflection); } WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); } else { WriteElements(RaCodeGen.GetStringForArrayMember(arrayName , "i" + arrayName, arrayTypeDesc), elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); } } Writer.Indent--; Writer.WriteLine("}"); }
void ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, string ns, XmlSchemaForm form, Type choiceIdentifierType) { int previousNestingLevel = arrayNestingLevel; XmlArrayItemAttributes previousArrayItemAttributes = savedArrayItemAttributes; string previousArrayNamespace = savedArrayNamespace; arrayNestingLevel = 0; savedArrayItemAttributes = null; savedArrayNamespace = null; Type accessorType = model.FieldType; string accessorName = model.Name; NameTable elements = new NameTable(); accessor.TypeDesc = typeScope.GetTypeDesc(accessorType); XmlAttributeFlags flags = a.XmlFlags; accessor.Ignore = a.XmlIgnore; CheckAmbiguousChoice(a, accessorType, accessorName); XmlAttributeFlags elemFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier; XmlAttributeFlags attrFlags = XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyAttribute; XmlAttributeFlags arrayFlags = XmlAttributeFlags.Array | XmlAttributeFlags.ArrayItems; // special case for byte[]. It can be a primitive (base64Binary or hexBinary), or it can // be an array of bytes. Our default is primitive; specify [XmlArray] to get array behavior. if ((flags & arrayFlags) != 0 && accessorType == typeof(byte[])) accessor.TypeDesc = typeScope.GetArrayTypeDesc(accessorType); if (a.XmlChoiceIdentifier != null) { accessor.ChoiceIdentifier = new ChoiceIdentifierAccessor(); accessor.ChoiceIdentifier.MemberName = a.XmlChoiceIdentifier.MemberName; accessor.ChoiceIdentifier.Mapping = ImportTypeMapping(modelScope.GetTypeModel(choiceIdentifierType), ns, ImportContext.Element, String.Empty); } if (accessor.TypeDesc.IsArrayLike) { Type arrayElementType = TypeScope.GetArrayElementType(accessorType); if ((flags & attrFlags) != 0) { if ((flags & attrFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttributesArrayAttribute)); if (a.XmlAttribute != null && !accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive && !accessor.TypeDesc.ArrayElementTypeDesc.IsEnum) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName)); bool isList = a.XmlAttribute != null && (accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive || accessor.TypeDesc.ArrayElementTypeDesc.IsEnum); if (a.XmlAnyAttribute != null) { a.XmlAttribute = new XmlAttributeAttribute(); } AttributeAccessor attribute = new AttributeAccessor(); Type targetType = a.XmlAttribute.Type == null ? arrayElementType : a.XmlAttribute.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); attribute.Name = Accessor.EscapeName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName, true); attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace; attribute.Form = a.XmlAttribute.Form; // == XmlSchemaForm.None ? form : a.XmlAttribute.Form; if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) { attribute.Form = XmlSchemaForm.Qualified; } attribute.CheckSpecial(); CheckForm(attribute.Form, ns != attribute.Namespace); attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, XmlSchemaForm.Qualified, isList); attribute.IsList = isList; attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); attribute.Any = (a.XmlAnyAttribute != null); accessor.Attribute = attribute; } else if ((flags & elemFlags) != 0) { if ((flags & elemFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalElementsArrayAttribute)); if (a.XmlText != null) { TextAccessor text = new TextAccessor(); Type targetType = a.XmlText.Type == null ? arrayElementType : a.XmlText.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); text.Name = accessorName; // unused except to make more helpful error messages text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Text, a.XmlText.DataType, XmlSchemaForm.Qualified, true); if (!(text.Mapping is SpecialMapping) && targetTypeDesc != typeScope.GetTypeDesc(typeof(string))) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayTextAttribute, accessorName)); accessor.Text = text; } if (a.XmlText == null && a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0) a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; Type targetType = xmlElement.Type == null ? arrayElementType : xmlElement.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); ElementAccessor element = new ElementAccessor(); element.Namespace = xmlElement.Namespace == null ? ns : xmlElement.Namespace; element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, xmlElement.DataType); if (a.XmlElements.Count == 1) { element.Name = Accessor.EscapeName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName, false); } else { element.Name = Accessor.EscapeName(xmlElement.ElementName.Length == 0 ? element.Mapping.TypeName : xmlElement.ElementName, false); } element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = xmlElement.IsNullable; element.Form = xmlElement.Form == XmlSchemaForm.None ? form : xmlElement.Form; CheckForm(element.Form, ns != element.Namespace); CheckNullable(element.IsNullable, targetTypeDesc); element = ReconcileLocalAccessor(element, ns); AddUniqueAccessor(elements, element); } for (int i = 0; i < a.XmlAnyElements.Count; i++) { XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i]; Type targetType = typeof(XmlNode).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlElement); ElementAccessor element = new ElementAccessor(); element.Name = Accessor.EscapeName(xmlAnyElement.Name, false); element.Namespace = xmlAnyElement.Namespace == null ? ns : xmlAnyElement.Namespace; element.Any = true; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); if (element.Name != String.Empty) typeModel.TypeDesc.IsMixed = true; else if (xmlAnyElement.Namespace != null) throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementNamespace, accessorName, xmlAnyElement.Namespace)); element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty); element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = false; element.Form = form; CheckForm(element.Form, ns != element.Namespace); CheckNullable(element.IsNullable, targetTypeDesc); element = ReconcileLocalAccessor(element, ns); elements.Add(element.Name, element.Namespace, element); } } else { if ((flags & arrayFlags) != 0) { if ((flags & arrayFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayArrayAttribute)); } TypeDesc arrayElementTypeDesc = typeScope.GetTypeDesc(arrayElementType); if (a.XmlArray == null) a.XmlArray = CreateArrayAttribute(accessor.TypeDesc); if (CountAtLevel(a.XmlArrayItems, arrayNestingLevel) == 0) a.XmlArrayItems.Add(CreateArrayItemAttribute(arrayElementTypeDesc, arrayNestingLevel)); ElementAccessor arrayElement = new ElementAccessor(); arrayElement.Name = Accessor.EscapeName(a.XmlArray.ElementName.Length == 0 ? accessorName : a.XmlArray.ElementName, false); arrayElement.Namespace = a.XmlArray.Namespace == null ? ns : a.XmlArray.Namespace; savedArrayItemAttributes = a.XmlArrayItems; savedArrayNamespace = arrayElement.Namespace; ArrayMapping arrayMapping = ImportArrayLikeMapping(modelScope.GetArrayModel(accessorType), ns, form); arrayElement.Mapping = arrayMapping; arrayElement.IsNullable = a.XmlArray.IsNullable; arrayElement.Form = a.XmlArray.Form == XmlSchemaForm.None ? form : a.XmlArray.Form; CheckForm(arrayElement.Form, ns != arrayElement.Namespace); CheckNullable(arrayElement.IsNullable, accessor.TypeDesc); savedArrayItemAttributes = null; savedArrayNamespace = null; arrayElement = ReconcileLocalAccessor(arrayElement, ns); AddUniqueAccessor(elements, arrayElement); } } else if (!accessor.TypeDesc.IsVoid) { XmlAttributeFlags allFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier | XmlAttributeFlags.XmlnsDeclarations; if ((flags & allFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute)); if (accessor.TypeDesc.IsPrimitive || accessor.TypeDesc.IsEnum) { if (a.XmlAnyElements.Count > 0) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement)); if (a.XmlAttribute != null) { if (a.XmlElements.Count > 0) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute)); if (a.XmlAttribute.Type != null) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlAttribute")); AttributeAccessor attribute = new AttributeAccessor(); attribute.Name = Accessor.EscapeName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName, true); attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace; attribute.Form = a.XmlAttribute.Form; // == XmlSchemaForm.None ? form : a.XmlAttribute.Form; if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) { attribute.Form = XmlSchemaForm.Qualified; } attribute.CheckSpecial(); CheckForm(attribute.Form, ns != attribute.Namespace); attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Attribute, a.XmlAttribute.DataType); attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); attribute.Any = a.XmlAnyAttribute != null; accessor.Attribute = attribute; } else { if (a.XmlText != null) { if (a.XmlText.Type != null && a.XmlText.Type != accessorType) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlText")); TextAccessor text = new TextAccessor(); text.Name = accessorName; // unused except to make more helpful error messages text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Text, a.XmlText.DataType); accessor.Text = text; } else if (a.XmlElements.Count == 0) { a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); } for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; if (xmlElement.Type != null) { if (typeScope.GetTypeDesc(xmlElement.Type) != accessor.TypeDesc) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlElement")); } ElementAccessor element = new ElementAccessor(); element.Name = Accessor.EscapeName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName, false); element.Namespace = xmlElement.Namespace == null ? ns : xmlElement.Namespace; element.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), element.Namespace, ImportContext.Element, xmlElement.DataType); element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = xmlElement.IsNullable; element.Form = xmlElement.Form == XmlSchemaForm.None ? form : xmlElement.Form; CheckForm(element.Form, ns != element.Namespace); CheckNullable(element.IsNullable, accessor.TypeDesc); element = ReconcileLocalAccessor(element, ns); AddUniqueAccessor(elements, element); } } } else if (a.Xmlns) { if (flags != XmlAttributeFlags.XmlnsDeclarations) throw new InvalidOperationException(Res.GetString(Res.XmlSoleXmlnsAttribute)); if (accessorType != typeof(XmlSerializerNamespaces)) { throw new InvalidOperationException(Res.GetString(Res.XmlXmlnsInvalidType, accessorName, accessorType.FullName, typeof(XmlSerializerNamespaces).FullName)); } accessor.Xmlns = new XmlnsAccessor(); accessor.Ignore = true; } else { if (a.XmlAttribute != null || a.XmlText != null) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName)); if (a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0) a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; Type targetType = xmlElement.Type == null ? accessorType : xmlElement.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); ElementAccessor element = new ElementAccessor(); TypeModel typeModel = modelScope.GetTypeModel(targetType); element.Namespace = xmlElement.Namespace == null ? ns : xmlElement.Namespace; element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, xmlElement.DataType); if (a.XmlElements.Count == 1) { element.Name = Accessor.EscapeName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName, false); } else { element.Name = Accessor.EscapeName(xmlElement.ElementName.Length == 0 ? element.Mapping.TypeName : xmlElement.ElementName, false); } element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = xmlElement.IsNullable; element.Form = xmlElement.Form == XmlSchemaForm.None ? form : xmlElement.Form; CheckForm(element.Form, ns != element.Namespace); CheckNullable(element.IsNullable, targetTypeDesc); element = ReconcileLocalAccessor(element, ns); AddUniqueAccessor(elements, element); } for (int i = 0; i < a.XmlAnyElements.Count; i++) { XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i]; Type targetType = typeof(XmlNode).IsAssignableFrom(accessorType) ? accessorType : typeof(XmlElement); ElementAccessor element = new ElementAccessor(); element.Name = Accessor.EscapeName(xmlAnyElement.Name, false); element.Namespace = xmlAnyElement.Namespace == null ? ns : xmlAnyElement.Namespace; element.Any = true; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); if (element.Name != String.Empty) typeModel.TypeDesc.IsMixed = true; else if (xmlAnyElement.Namespace != null) throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementNamespace, accessorName, xmlAnyElement.Namespace)); element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty); element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = false; element.Form = form; CheckForm(element.Form, ns != element.Namespace); CheckNullable(element.IsNullable, targetTypeDesc); element = ReconcileLocalAccessor(element, ns); elements.Add(element.Name, element.Namespace, element); } } } accessor.Elements = (ElementAccessor[])elements.ToArray(typeof(ElementAccessor)); if (accessor.ChoiceIdentifier != null) { // find the enum value corresponding to each element accessor.ChoiceIdentifier.MemberIds = new string[accessor.Elements.Length]; for (int i = 0; i < accessor.Elements.Length; i++) { bool found = false; ElementAccessor element = accessor.Elements[i]; EnumMapping choiceMapping = (EnumMapping)accessor.ChoiceIdentifier.Mapping; for (int j = 0; j < choiceMapping.Constants.Length; j++) { string xmlName = choiceMapping.Constants[j].XmlName; int colon = xmlName.LastIndexOf(':'); string choiceNs = colon < 0 ? element.Namespace : xmlName.Substring(0, colon); string choiceName = colon < 0 ? xmlName : xmlName.Substring(colon+1); if (element.Name == choiceName && element.Namespace == choiceNs) { accessor.ChoiceIdentifier.MemberIds[i] = choiceMapping.Constants[j].Name; found = true; break; } } if (!found) { // Type {0} is missing value for '{1}'. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName, element.Name)); } } } arrayNestingLevel = previousNestingLevel; savedArrayItemAttributes = previousArrayItemAttributes; savedArrayNamespace = previousArrayNamespace; }
private void ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, string ns, Type choiceIdentifierType, bool rpc, bool openModel, RecursionLimiter limiter) { XmlSchemaForm qualified = XmlSchemaForm.Qualified; int arrayNestingLevel = this.arrayNestingLevel; int order = -1; XmlArrayItemAttributes savedArrayItemAttributes = this.savedArrayItemAttributes; string savedArrayNamespace = this.savedArrayNamespace; this.arrayNestingLevel = 0; this.savedArrayItemAttributes = null; this.savedArrayNamespace = null; Type fieldType = model.FieldType; string name = model.Name; ArrayList list = new ArrayList(); System.Xml.Serialization.NameTable scope = new System.Xml.Serialization.NameTable(); accessor.TypeDesc = this.typeScope.GetTypeDesc(fieldType); XmlAttributeFlags xmlFlags = a.XmlFlags; accessor.Ignore = a.XmlIgnore; if (rpc) { this.CheckTopLevelAttributes(a, name); } else { this.CheckAmbiguousChoice(a, fieldType, name); } XmlAttributeFlags flags2 = XmlAttributeFlags.ChoiceIdentifier | XmlAttributeFlags.AnyElements | XmlAttributeFlags.Elements | XmlAttributeFlags.Text; XmlAttributeFlags flags3 = XmlAttributeFlags.AnyAttribute | XmlAttributeFlags.Attribute; XmlAttributeFlags flags4 = XmlAttributeFlags.ArrayItems | XmlAttributeFlags.Array; if (((xmlFlags & flags4) != ((XmlAttributeFlags) 0)) && (fieldType == typeof(byte[]))) { accessor.TypeDesc = this.typeScope.GetArrayTypeDesc(fieldType); } if (a.XmlChoiceIdentifier != null) { accessor.ChoiceIdentifier = new ChoiceIdentifierAccessor(); accessor.ChoiceIdentifier.MemberName = a.XmlChoiceIdentifier.MemberName; accessor.ChoiceIdentifier.Mapping = this.ImportTypeMapping(this.modelScope.GetTypeModel(choiceIdentifierType), ns, ImportContext.Element, string.Empty, null, limiter); this.CheckChoiceIdentifierMapping((EnumMapping) accessor.ChoiceIdentifier.Mapping); } if (accessor.TypeDesc.IsArrayLike) { Type arrayElementType = TypeScope.GetArrayElementType(fieldType, model.FieldTypeDesc.FullName + "." + model.Name); if ((xmlFlags & flags3) != ((XmlAttributeFlags) 0)) { if ((xmlFlags & flags3) != xmlFlags) { throw new InvalidOperationException(Res.GetString("XmlIllegalAttributesArrayAttribute")); } if (((a.XmlAttribute != null) && !accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive) && !accessor.TypeDesc.ArrayElementTypeDesc.IsEnum) { if (accessor.TypeDesc.ArrayElementTypeDesc.Kind == TypeKind.Serializable) { throw new InvalidOperationException(Res.GetString("XmlIllegalAttrOrTextInterface", new object[] { name, accessor.TypeDesc.ArrayElementTypeDesc.FullName, typeof(IXmlSerializable).Name })); } throw new InvalidOperationException(Res.GetString("XmlIllegalAttrOrText", new object[] { name, accessor.TypeDesc.ArrayElementTypeDesc.FullName })); } bool repeats = (a.XmlAttribute != null) && (accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive || accessor.TypeDesc.ArrayElementTypeDesc.IsEnum); if (a.XmlAnyAttribute != null) { a.XmlAttribute = new XmlAttributeAttribute(); } AttributeAccessor accessor2 = new AttributeAccessor(); Type type = (a.XmlAttribute.Type == null) ? arrayElementType : a.XmlAttribute.Type; this.typeScope.GetTypeDesc(type); accessor2.Name = Accessor.EscapeQName((a.XmlAttribute.AttributeName.Length == 0) ? name : a.XmlAttribute.AttributeName); accessor2.Namespace = (a.XmlAttribute.Namespace == null) ? ns : a.XmlAttribute.Namespace; accessor2.Form = a.XmlAttribute.Form; if ((accessor2.Form == XmlSchemaForm.None) && (ns != accessor2.Namespace)) { accessor2.Form = XmlSchemaForm.Qualified; } accessor2.CheckSpecial(); CheckForm(accessor2.Form, ns != accessor2.Namespace); accessor2.Mapping = this.ImportTypeMapping(this.modelScope.GetTypeModel(type), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null, repeats, false, limiter); accessor2.IsList = repeats; accessor2.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); accessor2.Any = a.XmlAnyAttribute != null; if ((accessor2.Form == XmlSchemaForm.Qualified) && (accessor2.Namespace != ns)) { if (this.xsdAttributes == null) { this.xsdAttributes = new System.Xml.Serialization.NameTable(); } accessor2 = (AttributeAccessor) this.ReconcileAccessor(accessor2, this.xsdAttributes); } accessor.Attribute = accessor2; } else if ((xmlFlags & flags2) != ((XmlAttributeFlags) 0)) { if ((xmlFlags & flags2) != xmlFlags) { throw new InvalidOperationException(Res.GetString("XmlIllegalElementsArrayAttribute")); } if (a.XmlText != null) { TextAccessor accessor3 = new TextAccessor(); Type type4 = (a.XmlText.Type == null) ? arrayElementType : a.XmlText.Type; TypeDesc typeDesc = this.typeScope.GetTypeDesc(type4); accessor3.Name = name; accessor3.Mapping = this.ImportTypeMapping(this.modelScope.GetTypeModel(type4), ns, ImportContext.Text, a.XmlText.DataType, null, true, false, limiter); if (!(accessor3.Mapping is SpecialMapping) && (typeDesc != this.typeScope.GetTypeDesc(typeof(string)))) { throw new InvalidOperationException(Res.GetString("XmlIllegalArrayTextAttribute", new object[] { name })); } accessor.Text = accessor3; } if (((a.XmlText == null) && (a.XmlElements.Count == 0)) && (a.XmlAnyElements.Count == 0)) { a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); } for (int i = 0; i < a.XmlElements.Count; i++) { ElementAccessor accessor4; XmlElementAttribute attribute = a.XmlElements[i]; Type type5 = (attribute.Type == null) ? arrayElementType : attribute.Type; TypeDesc desc2 = this.typeScope.GetTypeDesc(type5); TypeModel typeModel = this.modelScope.GetTypeModel(type5); accessor4 = new ElementAccessor { Namespace = rpc ? null : ((attribute.Namespace == null) ? ns : attribute.Namespace), Mapping = this.ImportTypeMapping(typeModel, rpc ? ns : accessor4.Namespace, ImportContext.Element, attribute.DataType, null, limiter) }; if (a.XmlElements.Count == 1) { accessor4.Name = XmlConvert.EncodeLocalName((attribute.ElementName.Length == 0) ? name : attribute.ElementName); } else { accessor4.Name = (attribute.ElementName.Length == 0) ? accessor4.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(attribute.ElementName); } accessor4.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if ((attribute.IsNullableSpecified && !attribute.IsNullable) && typeModel.TypeDesc.IsOptionalValue) { throw new InvalidOperationException(Res.GetString("XmlInvalidNotNullable", new object[] { typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement" })); } accessor4.IsNullable = attribute.IsNullableSpecified ? attribute.IsNullable : typeModel.TypeDesc.IsOptionalValue; accessor4.Form = rpc ? XmlSchemaForm.Unqualified : ((attribute.Form == XmlSchemaForm.None) ? qualified : attribute.Form); CheckNullable(accessor4.IsNullable, desc2, accessor4.Mapping); if (!rpc) { CheckForm(accessor4.Form, ns != accessor4.Namespace); accessor4 = this.ReconcileLocalAccessor(accessor4, ns); } if (attribute.Order != -1) { if ((attribute.Order != order) && (order != -1)) { throw new InvalidOperationException(Res.GetString("XmlSequenceMatch", new object[] { "Order" })); } order = attribute.Order; } AddUniqueAccessor(scope, accessor4); list.Add(accessor4); } System.Xml.Serialization.NameTable table2 = new System.Xml.Serialization.NameTable(); for (int j = 0; j < a.XmlAnyElements.Count; j++) { XmlAnyElementAttribute attribute2 = a.XmlAnyElements[j]; Type c = typeof(IXmlSerializable).IsAssignableFrom(arrayElementType) ? arrayElementType : (typeof(XmlNode).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlElement)); if (!arrayElementType.IsAssignableFrom(c)) { throw new InvalidOperationException(Res.GetString("XmlIllegalAnyElement", new object[] { arrayElementType.FullName })); } string str3 = (attribute2.Name.Length == 0) ? attribute2.Name : XmlConvert.EncodeLocalName(attribute2.Name); string str4 = attribute2.NamespaceSpecified ? attribute2.Namespace : null; if (table2[str3, str4] == null) { table2[str3, str4] = attribute2; if (scope[str3, (str4 == null) ? ns : str4] != null) { throw new InvalidOperationException(Res.GetString("XmlAnyElementDuplicate", new object[] { name, attribute2.Name, (attribute2.Namespace == null) ? "null" : attribute2.Namespace })); } ElementAccessor accessor5 = new ElementAccessor { Name = str3, Namespace = (str4 == null) ? ns : str4, Any = true, AnyNamespaces = str4 }; TypeDesc desc3 = this.typeScope.GetTypeDesc(c); TypeModel model3 = this.modelScope.GetTypeModel(c); if (accessor5.Name.Length > 0) { model3.TypeDesc.IsMixed = true; } accessor5.Mapping = this.ImportTypeMapping(model3, accessor5.Namespace, ImportContext.Element, string.Empty, null, limiter); accessor5.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); accessor5.IsNullable = false; accessor5.Form = qualified; CheckNullable(accessor5.IsNullable, desc3, accessor5.Mapping); if (!rpc) { CheckForm(accessor5.Form, ns != accessor5.Namespace); accessor5 = this.ReconcileLocalAccessor(accessor5, ns); } scope.Add(accessor5.Name, accessor5.Namespace, accessor5); list.Add(accessor5); if (attribute2.Order != -1) { if ((attribute2.Order != order) && (order != -1)) { throw new InvalidOperationException(Res.GetString("XmlSequenceMatch", new object[] { "Order" })); } order = attribute2.Order; } } } } else { if (((xmlFlags & flags4) != ((XmlAttributeFlags) 0)) && ((xmlFlags & flags4) != xmlFlags)) { throw new InvalidOperationException(Res.GetString("XmlIllegalArrayArrayAttribute")); } TypeDesc desc4 = this.typeScope.GetTypeDesc(arrayElementType); if (a.XmlArray == null) { a.XmlArray = CreateArrayAttribute(accessor.TypeDesc); } if (CountAtLevel(a.XmlArrayItems, this.arrayNestingLevel) == 0) { a.XmlArrayItems.Add(CreateArrayItemAttribute(desc4, this.arrayNestingLevel)); } ElementAccessor accessor6 = new ElementAccessor { Name = XmlConvert.EncodeLocalName((a.XmlArray.ElementName.Length == 0) ? name : a.XmlArray.ElementName), Namespace = rpc ? null : ((a.XmlArray.Namespace == null) ? ns : a.XmlArray.Namespace) }; this.savedArrayItemAttributes = a.XmlArrayItems; this.savedArrayNamespace = accessor6.Namespace; ArrayMapping mapping = this.ImportArrayLikeMapping(this.modelScope.GetArrayModel(fieldType), ns, limiter); accessor6.Mapping = mapping; accessor6.IsNullable = a.XmlArray.IsNullable; accessor6.Form = rpc ? XmlSchemaForm.Unqualified : ((a.XmlArray.Form == XmlSchemaForm.None) ? qualified : a.XmlArray.Form); order = a.XmlArray.Order; CheckNullable(accessor6.IsNullable, accessor.TypeDesc, accessor6.Mapping); if (!rpc) { CheckForm(accessor6.Form, ns != accessor6.Namespace); accessor6 = this.ReconcileLocalAccessor(accessor6, ns); } this.savedArrayItemAttributes = null; this.savedArrayNamespace = null; AddUniqueAccessor(scope, accessor6); list.Add(accessor6); } } else if (!accessor.TypeDesc.IsVoid) { XmlAttributeFlags flags5 = XmlAttributeFlags.XmlnsDeclarations | XmlAttributeFlags.ChoiceIdentifier | XmlAttributeFlags.AnyElements | XmlAttributeFlags.Attribute | XmlAttributeFlags.Elements | XmlAttributeFlags.Text; if ((xmlFlags & flags5) != xmlFlags) { throw new InvalidOperationException(Res.GetString("XmlIllegalAttribute")); } if (accessor.TypeDesc.IsPrimitive || accessor.TypeDesc.IsEnum) { if (a.XmlAnyElements.Count > 0) { throw new InvalidOperationException(Res.GetString("XmlIllegalAnyElement", new object[] { accessor.TypeDesc.FullName })); } if (a.XmlAttribute != null) { if (a.XmlElements.Count > 0) { throw new InvalidOperationException(Res.GetString("XmlIllegalAttribute")); } if (a.XmlAttribute.Type != null) { throw new InvalidOperationException(Res.GetString("XmlIllegalType", new object[] { "XmlAttribute" })); } AttributeAccessor accessor7 = new AttributeAccessor { Name = Accessor.EscapeQName((a.XmlAttribute.AttributeName.Length == 0) ? name : a.XmlAttribute.AttributeName), Namespace = (a.XmlAttribute.Namespace == null) ? ns : a.XmlAttribute.Namespace, Form = a.XmlAttribute.Form }; if ((accessor7.Form == XmlSchemaForm.None) && (ns != accessor7.Namespace)) { accessor7.Form = XmlSchemaForm.Qualified; } accessor7.CheckSpecial(); CheckForm(accessor7.Form, ns != accessor7.Namespace); accessor7.Mapping = this.ImportTypeMapping(this.modelScope.GetTypeModel(fieldType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null, limiter); accessor7.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); accessor7.Any = a.XmlAnyAttribute != null; if ((accessor7.Form == XmlSchemaForm.Qualified) && (accessor7.Namespace != ns)) { if (this.xsdAttributes == null) { this.xsdAttributes = new System.Xml.Serialization.NameTable(); } accessor7 = (AttributeAccessor) this.ReconcileAccessor(accessor7, this.xsdAttributes); } accessor.Attribute = accessor7; } else { if (a.XmlText != null) { if ((a.XmlText.Type != null) && (a.XmlText.Type != fieldType)) { throw new InvalidOperationException(Res.GetString("XmlIllegalType", new object[] { "XmlText" })); } TextAccessor accessor8 = new TextAccessor { Name = name, Mapping = this.ImportTypeMapping(this.modelScope.GetTypeModel(fieldType), ns, ImportContext.Text, a.XmlText.DataType, null, limiter) }; accessor.Text = accessor8; } else if (a.XmlElements.Count == 0) { a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); } for (int k = 0; k < a.XmlElements.Count; k++) { XmlElementAttribute attribute3 = a.XmlElements[k]; if ((attribute3.Type != null) && (this.typeScope.GetTypeDesc(attribute3.Type) != accessor.TypeDesc)) { throw new InvalidOperationException(Res.GetString("XmlIllegalType", new object[] { "XmlElement" })); } ElementAccessor accessor9 = new ElementAccessor { Name = XmlConvert.EncodeLocalName((attribute3.ElementName.Length == 0) ? name : attribute3.ElementName), Namespace = rpc ? null : ((attribute3.Namespace == null) ? ns : attribute3.Namespace) }; TypeModel model4 = this.modelScope.GetTypeModel(fieldType); accessor9.Mapping = this.ImportTypeMapping(model4, rpc ? ns : accessor9.Namespace, ImportContext.Element, attribute3.DataType, null, limiter); if (accessor9.Mapping.TypeDesc.Kind == TypeKind.Node) { accessor9.Any = true; } accessor9.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if ((attribute3.IsNullableSpecified && !attribute3.IsNullable) && model4.TypeDesc.IsOptionalValue) { throw new InvalidOperationException(Res.GetString("XmlInvalidNotNullable", new object[] { model4.TypeDesc.BaseTypeDesc.FullName, "XmlElement" })); } accessor9.IsNullable = attribute3.IsNullableSpecified ? attribute3.IsNullable : model4.TypeDesc.IsOptionalValue; accessor9.Form = rpc ? XmlSchemaForm.Unqualified : ((attribute3.Form == XmlSchemaForm.None) ? qualified : attribute3.Form); CheckNullable(accessor9.IsNullable, accessor.TypeDesc, accessor9.Mapping); if (!rpc) { CheckForm(accessor9.Form, ns != accessor9.Namespace); accessor9 = this.ReconcileLocalAccessor(accessor9, ns); } if (attribute3.Order != -1) { if ((attribute3.Order != order) && (order != -1)) { throw new InvalidOperationException(Res.GetString("XmlSequenceMatch", new object[] { "Order" })); } order = attribute3.Order; } AddUniqueAccessor(scope, accessor9); list.Add(accessor9); } } } else if (a.Xmlns) { if (xmlFlags != XmlAttributeFlags.XmlnsDeclarations) { throw new InvalidOperationException(Res.GetString("XmlSoleXmlnsAttribute")); } if (fieldType != typeof(XmlSerializerNamespaces)) { throw new InvalidOperationException(Res.GetString("XmlXmlnsInvalidType", new object[] { name, fieldType.FullName, typeof(XmlSerializerNamespaces).FullName })); } accessor.Xmlns = new XmlnsAccessor(); accessor.Ignore = true; } else { if ((a.XmlAttribute != null) || (a.XmlText != null)) { if (accessor.TypeDesc.Kind == TypeKind.Serializable) { throw new InvalidOperationException(Res.GetString("XmlIllegalAttrOrTextInterface", new object[] { name, accessor.TypeDesc.FullName, typeof(IXmlSerializable).Name })); } throw new InvalidOperationException(Res.GetString("XmlIllegalAttrOrText", new object[] { name, accessor.TypeDesc })); } if ((a.XmlElements.Count == 0) && (a.XmlAnyElements.Count == 0)) { a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); } for (int m = 0; m < a.XmlElements.Count; m++) { XmlElementAttribute attribute4 = a.XmlElements[m]; Type type7 = (attribute4.Type == null) ? fieldType : attribute4.Type; TypeDesc desc5 = this.typeScope.GetTypeDesc(type7); ElementAccessor accessor10 = new ElementAccessor(); TypeModel model5 = this.modelScope.GetTypeModel(type7); accessor10.Namespace = rpc ? null : ((attribute4.Namespace == null) ? ns : attribute4.Namespace); accessor10.Mapping = this.ImportTypeMapping(model5, rpc ? ns : accessor10.Namespace, ImportContext.Element, attribute4.DataType, null, false, openModel, limiter); if (a.XmlElements.Count == 1) { accessor10.Name = XmlConvert.EncodeLocalName((attribute4.ElementName.Length == 0) ? name : attribute4.ElementName); } else { accessor10.Name = (attribute4.ElementName.Length == 0) ? accessor10.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(attribute4.ElementName); } accessor10.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if ((attribute4.IsNullableSpecified && !attribute4.IsNullable) && model5.TypeDesc.IsOptionalValue) { throw new InvalidOperationException(Res.GetString("XmlInvalidNotNullable", new object[] { model5.TypeDesc.BaseTypeDesc.FullName, "XmlElement" })); } accessor10.IsNullable = attribute4.IsNullableSpecified ? attribute4.IsNullable : model5.TypeDesc.IsOptionalValue; accessor10.Form = rpc ? XmlSchemaForm.Unqualified : ((attribute4.Form == XmlSchemaForm.None) ? qualified : attribute4.Form); CheckNullable(accessor10.IsNullable, desc5, accessor10.Mapping); if (!rpc) { CheckForm(accessor10.Form, ns != accessor10.Namespace); accessor10 = this.ReconcileLocalAccessor(accessor10, ns); } if (attribute4.Order != -1) { if ((attribute4.Order != order) && (order != -1)) { throw new InvalidOperationException(Res.GetString("XmlSequenceMatch", new object[] { "Order" })); } order = attribute4.Order; } AddUniqueAccessor(scope, accessor10); list.Add(accessor10); } System.Xml.Serialization.NameTable table3 = new System.Xml.Serialization.NameTable(); for (int n = 0; n < a.XmlAnyElements.Count; n++) { XmlAnyElementAttribute attribute5 = a.XmlAnyElements[n]; Type type8 = typeof(IXmlSerializable).IsAssignableFrom(fieldType) ? fieldType : (typeof(XmlNode).IsAssignableFrom(fieldType) ? fieldType : typeof(XmlElement)); if (!fieldType.IsAssignableFrom(type8)) { throw new InvalidOperationException(Res.GetString("XmlIllegalAnyElement", new object[] { fieldType.FullName })); } string str5 = (attribute5.Name.Length == 0) ? attribute5.Name : XmlConvert.EncodeLocalName(attribute5.Name); string str6 = attribute5.NamespaceSpecified ? attribute5.Namespace : null; if (table3[str5, str6] == null) { table3[str5, str6] = attribute5; if (scope[str5, (str6 == null) ? ns : str6] != null) { throw new InvalidOperationException(Res.GetString("XmlAnyElementDuplicate", new object[] { name, attribute5.Name, (attribute5.Namespace == null) ? "null" : attribute5.Namespace })); } ElementAccessor accessor11 = new ElementAccessor { Name = str5, Namespace = (str6 == null) ? ns : str6, Any = true, AnyNamespaces = str6 }; TypeDesc desc6 = this.typeScope.GetTypeDesc(type8); TypeModel model6 = this.modelScope.GetTypeModel(type8); if (accessor11.Name.Length > 0) { model6.TypeDesc.IsMixed = true; } accessor11.Mapping = this.ImportTypeMapping(model6, accessor11.Namespace, ImportContext.Element, string.Empty, null, false, openModel, limiter); accessor11.Default = this.GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); accessor11.IsNullable = false; accessor11.Form = qualified; CheckNullable(accessor11.IsNullable, desc6, accessor11.Mapping); if (!rpc) { CheckForm(accessor11.Form, ns != accessor11.Namespace); accessor11 = this.ReconcileLocalAccessor(accessor11, ns); } if (attribute5.Order != -1) { if ((attribute5.Order != order) && (order != -1)) { throw new InvalidOperationException(Res.GetString("XmlSequenceMatch", new object[] { "Order" })); } order = attribute5.Order; } scope.Add(accessor11.Name, accessor11.Namespace, accessor11); list.Add(accessor11); } } } } accessor.Elements = (ElementAccessor[]) list.ToArray(typeof(ElementAccessor)); accessor.SequenceId = order; if (rpc) { if ((accessor.TypeDesc.IsArrayLike && (accessor.Elements.Length > 0)) && !(accessor.Elements[0].Mapping is ArrayMapping)) { throw new InvalidOperationException(Res.GetString("XmlRpcLitArrayElement", new object[] { accessor.Elements[0].Name })); } if (accessor.Xmlns != null) { throw new InvalidOperationException(Res.GetString("XmlRpcLitXmlns", new object[] { accessor.Name })); } } if (accessor.ChoiceIdentifier != null) { accessor.ChoiceIdentifier.MemberIds = new string[accessor.Elements.Length]; for (int num8 = 0; num8 < accessor.Elements.Length; num8++) { bool flag2 = false; ElementAccessor accessor12 = accessor.Elements[num8]; EnumMapping mapping2 = (EnumMapping) accessor.ChoiceIdentifier.Mapping; for (int num9 = 0; num9 < mapping2.Constants.Length; num9++) { string xmlName = mapping2.Constants[num9].XmlName; if (accessor12.Any && (accessor12.Name.Length == 0)) { string str8 = (accessor12.AnyNamespaces == null) ? "##any" : accessor12.AnyNamespaces; if (!(xmlName.Substring(0, xmlName.Length - 1) == str8)) { continue; } accessor.ChoiceIdentifier.MemberIds[num8] = mapping2.Constants[num9].Name; flag2 = true; break; } int length = xmlName.LastIndexOf(':'); string str9 = (length < 0) ? mapping2.Namespace : xmlName.Substring(0, length); string str10 = (length < 0) ? xmlName : xmlName.Substring(length + 1); if ((accessor12.Name == str10) && (((accessor12.Form == XmlSchemaForm.Unqualified) && string.IsNullOrEmpty(str9)) || (accessor12.Namespace == str9))) { accessor.ChoiceIdentifier.MemberIds[num8] = mapping2.Constants[num9].Name; flag2 = true; break; } } if (!flag2) { if (accessor12.Any && (accessor12.Name.Length == 0)) { throw new InvalidOperationException(Res.GetString("XmlChoiceMissingAnyValue", new object[] { accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName })); } string str11 = ((accessor12.Namespace != null) && (accessor12.Namespace.Length > 0)) ? (accessor12.Namespace + ":" + accessor12.Name) : accessor12.Name; throw new InvalidOperationException(Res.GetString("XmlChoiceMissingValue", new object[] { accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName, str11, accessor12.Name, accessor12.Namespace })); } } } this.arrayNestingLevel = arrayNestingLevel; this.savedArrayItemAttributes = savedArrayItemAttributes; this.savedArrayNamespace = savedArrayNamespace; }
void ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, string ns, Type choiceIdentifierType, bool rpc, bool openModel) { XmlSchemaForm elementFormDefault = XmlSchemaForm.Qualified; int previousNestingLevel = arrayNestingLevel; int sequenceId = -1; XmlArrayItemAttributes previousArrayItemAttributes = savedArrayItemAttributes; string previousArrayNamespace = savedArrayNamespace; arrayNestingLevel = 0; savedArrayItemAttributes = null; savedArrayNamespace = null; Type accessorType = model.FieldType; string accessorName = model.Name; ArrayList elementList = new ArrayList(); NameTable elements = new NameTable(); accessor.TypeDesc = typeScope.GetTypeDesc(accessorType); XmlAttributeFlags flags = a.XmlFlags; accessor.Ignore = a.XmlIgnore; if (rpc) CheckTopLevelAttributes(a, accessorName); else CheckAmbiguousChoice(a, accessorType, accessorName); XmlAttributeFlags elemFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier; XmlAttributeFlags attrFlags = XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyAttribute; XmlAttributeFlags arrayFlags = XmlAttributeFlags.Array | XmlAttributeFlags.ArrayItems; // special case for byte[]. It can be a primitive (base64Binary or hexBinary), or it can // be an array of bytes. Our default is primitive; specify [XmlArray] to get array behavior. if ((flags & arrayFlags) != 0 && accessorType == typeof(byte[])) accessor.TypeDesc = typeScope.GetArrayTypeDesc(accessorType); if (a.XmlChoiceIdentifier != null) { accessor.ChoiceIdentifier = new ChoiceIdentifierAccessor(); accessor.ChoiceIdentifier.MemberName = a.XmlChoiceIdentifier.MemberName; accessor.ChoiceIdentifier.Mapping = ImportTypeMapping(modelScope.GetTypeModel(choiceIdentifierType), ns, ImportContext.Element, String.Empty, null); CheckChoiceIdentifierMapping((EnumMapping)accessor.ChoiceIdentifier.Mapping); } if (accessor.TypeDesc.IsArrayLike) { Type arrayElementType = TypeScope.GetArrayElementType(accessorType, model.FieldTypeDesc.FullName + "." + model.Name); if ((flags & attrFlags) != 0) { if ((flags & attrFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttributesArrayAttribute)); if (a.XmlAttribute != null && !accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive && !accessor.TypeDesc.ArrayElementTypeDesc.IsEnum) { if (accessor.TypeDesc.ArrayElementTypeDesc.Kind == TypeKind.Serializable) { throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrTextInterface, accessorName, accessor.TypeDesc.ArrayElementTypeDesc.FullName, typeof(IXmlSerializable).Name)); } else { throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName, accessor.TypeDesc.ArrayElementTypeDesc.FullName)); } } bool isList = a.XmlAttribute != null && (accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive || accessor.TypeDesc.ArrayElementTypeDesc.IsEnum); if (a.XmlAnyAttribute != null) { a.XmlAttribute = new XmlAttributeAttribute(); } AttributeAccessor attribute = new AttributeAccessor(); Type targetType = a.XmlAttribute.Type == null ? arrayElementType : a.XmlAttribute.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); attribute.Name = Accessor.EscapeQName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName); attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace; attribute.Form = a.XmlAttribute.Form; if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) { attribute.Form = XmlSchemaForm.Qualified; } attribute.CheckSpecial(); CheckForm(attribute.Form, ns != attribute.Namespace); attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null, isList, false); attribute.IsList = isList; attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); attribute.Any = (a.XmlAnyAttribute != null); if (attribute.Form == XmlSchemaForm.Qualified && attribute.Namespace != ns) { if (xsdAttributes == null) xsdAttributes = new NameTable(); attribute = (AttributeAccessor)ReconcileAccessor(attribute, xsdAttributes); } accessor.Attribute = attribute; } else if ((flags & elemFlags) != 0) { if ((flags & elemFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalElementsArrayAttribute)); if (a.XmlText != null) { TextAccessor text = new TextAccessor(); Type targetType = a.XmlText.Type == null ? arrayElementType : a.XmlText.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); text.Name = accessorName; // unused except to make more helpful error messages text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Text, a.XmlText.DataType, null, true, false); if (!(text.Mapping is SpecialMapping) && targetTypeDesc != typeScope.GetTypeDesc(typeof(string))) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayTextAttribute, accessorName)); accessor.Text = text; } if (a.XmlText == null && a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0) a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; Type targetType = xmlElement.Type == null ? arrayElementType : xmlElement.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); ElementAccessor element = new ElementAccessor(); element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace; element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null); if (a.XmlElements.Count == 1) { element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName); //element.IsUnbounded = element.Mapping is ArrayMapping; } else { element.Name = xmlElement.ElementName.Length == 0 ? element.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(xmlElement.ElementName); } element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement")); element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue; element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form; CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping); if (!rpc) { CheckForm(element.Form, ns != element.Namespace); element = ReconcileLocalAccessor(element, ns); } if (xmlElement.Order != -1) { if (xmlElement.Order != sequenceId && sequenceId != -1) throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order")); sequenceId = xmlElement.Order; } AddUniqueAccessor(elements, element); elementList.Add(element); } NameTable anys = new NameTable(); for (int i = 0; i < a.XmlAnyElements.Count; i++) { XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i]; Type targetType = typeof(IXmlSerializable).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlNode).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlElement); if (!arrayElementType.IsAssignableFrom(targetType)) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, arrayElementType.FullName)); string anyName = xmlAnyElement.Name.Length == 0 ? xmlAnyElement.Name : XmlConvert.EncodeLocalName(xmlAnyElement.Name); string anyNs = xmlAnyElement.NamespaceSpecified ? xmlAnyElement.Namespace : null; if (anys[anyName, anyNs] != null) { // ignore duplicate anys continue; } anys[anyName, anyNs] = xmlAnyElement; if (elements[anyName, (anyNs == null ? ns : anyNs)] != null) { throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementDuplicate, accessorName, xmlAnyElement.Name, xmlAnyElement.Namespace == null ? "null" : xmlAnyElement.Namespace)); } ElementAccessor element = new ElementAccessor(); element.Name = anyName; element.Namespace = anyNs == null ? ns : anyNs; element.Any = true; element.AnyNamespaces = anyNs; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); if (element.Name.Length > 0) typeModel.TypeDesc.IsMixed = true; element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty, null); element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = false; element.Form = elementFormDefault; CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping); if (!rpc) { CheckForm(element.Form, ns != element.Namespace); element = ReconcileLocalAccessor(element, ns); } elements.Add(element.Name, element.Namespace, element); elementList.Add(element); if (xmlAnyElement.Order != -1) { if (xmlAnyElement.Order != sequenceId && sequenceId != -1) throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order")); sequenceId = xmlAnyElement.Order; } } } else { if ((flags & arrayFlags) != 0) { if ((flags & arrayFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayArrayAttribute)); } TypeDesc arrayElementTypeDesc = typeScope.GetTypeDesc(arrayElementType); if (a.XmlArray == null) a.XmlArray = CreateArrayAttribute(accessor.TypeDesc); if (CountAtLevel(a.XmlArrayItems, arrayNestingLevel) == 0) a.XmlArrayItems.Add(CreateArrayItemAttribute(arrayElementTypeDesc, arrayNestingLevel)); ElementAccessor arrayElement = new ElementAccessor(); arrayElement.Name = XmlConvert.EncodeLocalName(a.XmlArray.ElementName.Length == 0 ? accessorName : a.XmlArray.ElementName); arrayElement.Namespace = rpc ? null : a.XmlArray.Namespace == null ? ns : a.XmlArray.Namespace; savedArrayItemAttributes = a.XmlArrayItems; savedArrayNamespace = arrayElement.Namespace; ArrayMapping arrayMapping = ImportArrayLikeMapping(modelScope.GetArrayModel(accessorType), ns); arrayElement.Mapping = arrayMapping; arrayElement.IsNullable = a.XmlArray.IsNullable; arrayElement.Form = rpc ? XmlSchemaForm.Unqualified : a.XmlArray.Form == XmlSchemaForm.None ? elementFormDefault : a.XmlArray.Form; sequenceId = a.XmlArray.Order; CheckNullable(arrayElement.IsNullable, accessor.TypeDesc, arrayElement.Mapping); if (!rpc) { CheckForm(arrayElement.Form, ns != arrayElement.Namespace); arrayElement = ReconcileLocalAccessor(arrayElement, ns); } savedArrayItemAttributes = null; savedArrayNamespace = null; AddUniqueAccessor(elements, arrayElement); elementList.Add(arrayElement); } } else if (!accessor.TypeDesc.IsVoid) { XmlAttributeFlags allFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier | XmlAttributeFlags.XmlnsDeclarations; if ((flags & allFlags) != flags) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute)); if (accessor.TypeDesc.IsPrimitive || accessor.TypeDesc.IsEnum) { if (a.XmlAnyElements.Count > 0) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, accessor.TypeDesc.FullName)); if (a.XmlAttribute != null) { if (a.XmlElements.Count > 0) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute)); if (a.XmlAttribute.Type != null) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlAttribute")); AttributeAccessor attribute = new AttributeAccessor(); attribute.Name = Accessor.EscapeQName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName); attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace; attribute.Form = a.XmlAttribute.Form; if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) { attribute.Form = XmlSchemaForm.Qualified; } attribute.CheckSpecial(); CheckForm(attribute.Form, ns != attribute.Namespace); attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null); attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); attribute.Any = a.XmlAnyAttribute != null; if (attribute.Form == XmlSchemaForm.Qualified && attribute.Namespace != ns) { if (xsdAttributes == null) xsdAttributes = new NameTable(); attribute = (AttributeAccessor)ReconcileAccessor(attribute, xsdAttributes); } accessor.Attribute = attribute; } else { if (a.XmlText != null) { if (a.XmlText.Type != null && a.XmlText.Type != accessorType) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlText")); TextAccessor text = new TextAccessor(); text.Name = accessorName; // unused except to make more helpful error messages text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Text, a.XmlText.DataType, null); accessor.Text = text; } else if (a.XmlElements.Count == 0) { a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); } for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; if (xmlElement.Type != null) { if (typeScope.GetTypeDesc(xmlElement.Type) != accessor.TypeDesc) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlElement")); } ElementAccessor element = new ElementAccessor(); element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName); element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace; TypeModel typeModel = modelScope.GetTypeModel(accessorType); element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null); if (element.Mapping.TypeDesc.Kind == TypeKind.Node) { element.Any = true; } element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement")); element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue; element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form; CheckNullable(element.IsNullable, accessor.TypeDesc, element.Mapping); if (!rpc) { CheckForm(element.Form, ns != element.Namespace); element = ReconcileLocalAccessor(element, ns); } if (xmlElement.Order != -1) { if (xmlElement.Order != sequenceId && sequenceId != -1) throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order")); sequenceId = xmlElement.Order; } AddUniqueAccessor(elements, element); elementList.Add(element); } } } else if (a.Xmlns) { if (flags != XmlAttributeFlags.XmlnsDeclarations) throw new InvalidOperationException(Res.GetString(Res.XmlSoleXmlnsAttribute)); if (accessorType != typeof(XmlSerializerNamespaces)) { throw new InvalidOperationException(Res.GetString(Res.XmlXmlnsInvalidType, accessorName, accessorType.FullName, typeof(XmlSerializerNamespaces).FullName)); } accessor.Xmlns = new XmlnsAccessor(); accessor.Ignore = true; } else { if (a.XmlAttribute != null || a.XmlText != null) { if (accessor.TypeDesc.Kind == TypeKind.Serializable) { throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrTextInterface, accessorName, accessor.TypeDesc.FullName, typeof(IXmlSerializable).Name)); } else { throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName, accessor.TypeDesc)); } } if (a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0) a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc)); for (int i = 0; i < a.XmlElements.Count; i++) { XmlElementAttribute xmlElement = a.XmlElements[i]; Type targetType = xmlElement.Type == null ? accessorType : xmlElement.Type; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); ElementAccessor element = new ElementAccessor(); TypeModel typeModel = modelScope.GetTypeModel(targetType); element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace; element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null, false, openModel); if (a.XmlElements.Count == 1) { element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName); } else { element.Name = xmlElement.ElementName.Length == 0 ? element.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(xmlElement.ElementName); } element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue) throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement")); element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue; element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form; CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping); if (!rpc) { CheckForm(element.Form, ns != element.Namespace); element = ReconcileLocalAccessor(element, ns); } if (xmlElement.Order != -1) { if (xmlElement.Order != sequenceId && sequenceId != -1) throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order")); sequenceId = xmlElement.Order; } AddUniqueAccessor(elements, element); elementList.Add(element); } NameTable anys = new NameTable(); for (int i = 0; i < a.XmlAnyElements.Count; i++) { XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i]; Type targetType = typeof(IXmlSerializable).IsAssignableFrom(accessorType) ? accessorType : typeof(XmlNode).IsAssignableFrom(accessorType) ? accessorType : typeof(XmlElement); if (!accessorType.IsAssignableFrom(targetType)) throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, accessorType.FullName)); string anyName = xmlAnyElement.Name.Length == 0 ? xmlAnyElement.Name : XmlConvert.EncodeLocalName(xmlAnyElement.Name); string anyNs = xmlAnyElement.NamespaceSpecified ? xmlAnyElement.Namespace : null; if (anys[anyName, anyNs] != null) { // ignore duplicate anys continue; } anys[anyName, anyNs] = xmlAnyElement; if (elements[anyName, (anyNs == null ? ns : anyNs)] != null) { throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementDuplicate, accessorName, xmlAnyElement.Name, xmlAnyElement.Namespace == null ? "null" : xmlAnyElement.Namespace)); } ElementAccessor element = new ElementAccessor(); element.Name = anyName; element.Namespace = anyNs == null ? ns : anyNs; element.Any = true; element.AnyNamespaces = anyNs; TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType); TypeModel typeModel = modelScope.GetTypeModel(targetType); if (element.Name.Length > 0) typeModel.TypeDesc.IsMixed = true; element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty, null, false, openModel); element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a); element.IsNullable = false; element.Form = elementFormDefault; CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping); if (!rpc) { CheckForm(element.Form, ns != element.Namespace); element = ReconcileLocalAccessor(element, ns); } if (xmlAnyElement.Order != -1) { if (xmlAnyElement.Order != sequenceId && sequenceId != -1) throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order")); sequenceId = xmlAnyElement.Order; } elements.Add(element.Name, element.Namespace, element); elementList.Add(element); } } } accessor.Elements = (ElementAccessor[])elementList.ToArray(typeof(ElementAccessor)); accessor.SequenceId = sequenceId; if (rpc) { if (accessor.TypeDesc.IsArrayLike && accessor.Elements.Length > 0 && !(accessor.Elements[0].Mapping is ArrayMapping)) throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitArrayElement, accessor.Elements[0].Name)); if (accessor.Xmlns != null) throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitXmlns, accessor.Name)); } if (accessor.ChoiceIdentifier != null) { // find the enum value corresponding to each element accessor.ChoiceIdentifier.MemberIds = new string[accessor.Elements.Length]; for (int i = 0; i < accessor.Elements.Length; i++) { bool found = false; ElementAccessor element = accessor.Elements[i]; EnumMapping choiceMapping = (EnumMapping)accessor.ChoiceIdentifier.Mapping; for (int j = 0; j < choiceMapping.Constants.Length; j++) { string xmlName = choiceMapping.Constants[j].XmlName; if (element.Any && element.Name.Length == 0) { string anyNs = element.AnyNamespaces == null ? "##any" : element.AnyNamespaces; if (xmlName.Substring(0, xmlName.Length-1) == anyNs) { accessor.ChoiceIdentifier.MemberIds[i] = choiceMapping.Constants[j].Name; found = true; break; } continue; } int colon = xmlName.LastIndexOf(':'); string choiceNs = colon < 0 ? choiceMapping.Namespace : xmlName.Substring(0, colon); string choiceName = colon < 0 ? xmlName : xmlName.Substring(colon+1); if (element.Name == choiceName) { if ((element.Form == XmlSchemaForm.Unqualified && string.IsNullOrEmpty(choiceNs)) || element.Namespace == choiceNs) { accessor.ChoiceIdentifier.MemberIds[i] = choiceMapping.Constants[j].Name; found = true; break; } } } if (!found) { if (element.Any && element.Name.Length == 0) { // Type {0} is missing enumeration value '##any' for XmlAnyElementAttribute. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingAnyValue, accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName)); } else { string id = element.Namespace != null && element.Namespace.Length > 0 ? element.Namespace + ":" + element.Name : element.Name; // Type {0} is missing value for '{1}'. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName, id, element.Name, element.Namespace)); } } } } arrayNestingLevel = previousNestingLevel; savedArrayItemAttributes = previousArrayItemAttributes; savedArrayNamespace = previousArrayNamespace; }
void WriteArray(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) { if (elements.Length == 0 && text == null) return; Writer.WriteLine("{"); Writer.Indent++; string arrayTypeName = arrayTypeDesc.CSharpName; WriteArrayLocalDecl(arrayTypeName, "a", source, arrayTypeDesc); if (arrayTypeDesc.IsNullable) { Writer.WriteLine("if (a != null) {"); Writer.Indent++; } if (choice != null) { bool choiceUseReflection = choice.Mapping.TypeDesc.UseReflection; string choiceFullName = choice.Mapping.TypeDesc.CSharpName; WriteArrayLocalDecl(choiceFullName+"[]", "c", choiceSource, choice.Mapping.TypeDesc); // write check for the choice identifier array Writer.WriteLine("if (c == null || c.Length < a.Length) {"); Writer.Indent++; Writer.Write("throw CreateInvalidChoiceIdentifierValueException("); WriteQuotedCSharpString(choice.Mapping.TypeDesc.FullName); Writer.Write(", "); WriteQuotedCSharpString(choice.MemberName); Writer.Write(");"); Writer.Indent--; Writer.WriteLine("}"); } WriteArrayItems(elements, text, choice, arrayTypeDesc, "a", "c"); if (arrayTypeDesc.IsNullable) { Writer.Indent--; Writer.WriteLine("}"); } Writer.Indent--; Writer.WriteLine("}"); }
void WriteElements(string source, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) { WriteElements(source, null, elements, text, choice, arrayName, writeAccessors, isNullable); }
private void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, object o) { TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; var a = o as IEnumerable; // #10593: This assert may not be true. We need more tests for this method. Debug.Assert(a != null); var e = a.GetEnumerator(); if (e != null) { while (e.MoveNext()) { object ai = e.Current; WriteElements(ai, null/*choiceName + "i"*/, elements, text, choice, (string)null/*arrayName + "a"*/, true, true); } } }
void WriteText(string source, TextAccessor text) { if (text.Mapping is PrimitiveMapping) { PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; Writer.Write("WriteValue("); if (text.Mapping is EnumMapping) { WriteEnumValue((EnumMapping)text.Mapping, source); } else { WritePrimitiveValue(mapping.TypeDesc, source, false); } Writer.WriteLine(");"); } else if (text.Mapping is SpecialMapping) { SpecialMapping mapping = (SpecialMapping)text.Mapping; switch (mapping.TypeDesc.Kind) { case TypeKind.Node: Writer.Write(source); Writer.WriteLine(".WriteTo(Writer);"); break; default: throw new InvalidOperationException(Res.GetString(Res.XmlInternalError)); } } }
void WriteElements(string source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) { if (elements.Length == 0 && text == null) return; if (elements.Length == 1 && text == null) { WriteElement("((" + CodeIdentifier.EscapeKeywords(((TypeMapping)elements[0].Mapping).TypeDesc.FullName) + ")" + source + ")", elements[0], arrayName, writeAccessors); } else { writer.WriteLine("{"); writer.Indent++; int anyCount = 0; ArrayList namedAnys = new ArrayList(); ElementAccessor unnamedAny = null; // can only have one bool wroteFirstIf = false; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (choice != null) { string fullTypeName = CodeIdentifier.EscapeKeywords(((TypeMapping)element.Mapping).TypeDesc.FullName); string enumTypeName = CodeIdentifier.EscapeKeywords(choice.Mapping.TypeDesc.FullName); string enumFullName = enumTypeName + ".@"; string enumValue = null; EnumMapping choiceMapping = (EnumMapping)choice.Mapping; for (int j = 0; j < choiceMapping.Constants.Length; j++) { string xmlName = choiceMapping.Constants[j].XmlName; int colon = xmlName.LastIndexOf(':'); string choiceNs = colon < 0 ? element.Namespace : xmlName.Substring(0, colon); string choiceName = colon < 0 ? xmlName : xmlName.Substring(colon+1); if (element.Name == choiceName && element.Namespace == choiceNs) { enumValue = choiceMapping.Constants[j].Name; break; } } if (enumValue == null || enumValue.Length == 0) { // Type {0} is missing value for '{1}'. throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, choiceMapping.TypeDesc.FullName, element.Name)); } enumFullName += enumValue; if (wroteFirstIf) writer.Write("else "); else wroteFirstIf = true; writer.Write("if ("); writer.Write(enumSource); writer.Write(" == "); writer.Write(enumFullName); writer.WriteLine(") {"); writer.Indent++; WriteChoiceTypeCheck(source, fullTypeName, choice, enumFullName); WriteElement("((" + fullTypeName + ")" + source + ")", element, arrayName, writeAccessors); writer.Indent--; writer.WriteLine("}"); } else if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) namedAnys.Add(element); else if (unnamedAny == null) unnamedAny = element; } else { string fullTypeName = CodeIdentifier.EscapeKeywords(((TypeMapping)element.Mapping).TypeDesc.FullName); if (wroteFirstIf) writer.Write("else "); else wroteFirstIf = true; writer.Write("if ("); writer.Write(source); writer.Write(" is "); writer.Write(fullTypeName); writer.WriteLine(") {"); writer.Indent++; WriteElement("((" + fullTypeName + ")" + source + ")", element, arrayName, writeAccessors); writer.Indent--; writer.WriteLine("}"); } } if (anyCount > 0) { if (elements.Length - anyCount > 0) writer.Write("else "); string fullTypeName = typeof(XmlElement).FullName; writer.Write("if ("); writer.Write(source); writer.Write(" is "); writer.Write(fullTypeName); writer.WriteLine(") {"); writer.Indent++; writer.Write(fullTypeName); writer.Write(" elem = ("); writer.Write(fullTypeName); writer.Write(")"); writer.Write(source); writer.WriteLine(";"); int c = 0; foreach (ElementAccessor element in namedAnys) { if (c++ > 0) writer.Write("else "); writer.Write("if (elem.Name == "); WriteQuotedCSharpString(element.Name); writer.Write(" && elem.NamespaceURI == "); WriteQuotedCSharpString(element.Namespace); writer.WriteLine(") {"); writer.Indent++; WriteElement("elem", element, arrayName, writeAccessors); writer.Indent--; writer.WriteLine("}"); } if (c > 0) { writer.WriteLine("else {"); writer.Indent++; } if (unnamedAny != null) { WriteElement("elem", unnamedAny, arrayName, writeAccessors); } else { writer.WriteLine("throw CreateUnknownAnyElementException(elem.Name, elem.NamespaceURI);"); } if (c > 0) { writer.Indent--; writer.WriteLine("}"); } writer.Indent--; writer.WriteLine("}"); } if (text != null) { string fullTypeName = CodeIdentifier.EscapeKeywords(text.Mapping.TypeDesc.FullName); if (elements.Length > 0) { writer.Write("else "); writer.Write("if ("); writer.Write(source); writer.Write(" is "); writer.Write(fullTypeName); writer.WriteLine(") {"); writer.Indent++; WriteText("((" + fullTypeName + ")" + source + ")", text); writer.Indent--; writer.WriteLine("}"); } else { WriteText("((" + fullTypeName + ")" + source + ")", text); } } if (elements.Length > 0) { writer.WriteLine("else {"); writer.Indent++; if (isNullable) { writer.Write("if ("); writer.Write(source); writer.WriteLine(" != null) {"); writer.Indent++; } writer.Write("throw CreateUnknownTypeException("); writer.Write(source); writer.WriteLine(");"); if (isNullable) { writer.Indent--; writer.WriteLine("}"); } writer.Indent--; writer.WriteLine("}"); } writer.Indent--; writer.WriteLine("}"); } }