private void WriteElement()

in src/dotnet-svcutil/lib/src/FrameworkFork/Microsoft.Xml/Xml/Serialization/XmlSerializationWriterILGen.cs [2008:2186]


        private void WriteElement(SourceInfo source, ElementAccessor element, string arrayName, bool writeAccessor)
        {
            string name = writeAccessor ? element.Name : element.Mapping.TypeName;
            string ns = element.Any && element.Name.Length == 0 ? null : (element.Form == XmlSchemaForm.Qualified ? (writeAccessor ? element.Namespace : element.Mapping.Namespace) : "");
            if (element.Mapping is NullableMapping)
            {
                if (source.Type == element.Mapping.TypeDesc.Type)
                {
                    MethodInfo Nullable_get_HasValue = element.Mapping.TypeDesc.Type.GetMethod(
                        "get_HasValue",
                        CodeGenerator.InstanceBindingFlags,
                        null,
                        CodeGenerator.EmptyTypeArray,
                        null
                        );
                    source.LoadAddress(element.Mapping.TypeDesc.Type);
                    ilg.Call(Nullable_get_HasValue);
                }
                else
                {
                    source.Load(null);
                    ilg.Load(null);
                    ilg.Cne();
                }
                ilg.If();
                string fullTypeName = element.Mapping.TypeDesc.BaseTypeDesc.CSharpName;
                SourceInfo castedSource = source.CastTo(element.Mapping.TypeDesc.BaseTypeDesc);
                ElementAccessor e = element.Clone();
                e.Mapping = ((NullableMapping)element.Mapping).BaseMapping;
                WriteElement(e.Any ? source : castedSource, e, arrayName, writeAccessor);
                if (element.IsNullable)
                {
                    ilg.Else();
                    WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
                }
                ilg.EndIf();
            }
            else if (element.Mapping is ArrayMapping)
            {
                ArrayMapping mapping = (ArrayMapping)element.Mapping;
                if (element.IsUnbounded)
                {
                    throw CodeGenerator.NotSupported("Unreachable: IsUnbounded is never set true!");
                }
                else
                {
                    ilg.EnterScope();
                    string fullTypeName = mapping.TypeDesc.CSharpName;
                    WriteArrayLocalDecl(fullTypeName, arrayName, source, mapping.TypeDesc);
                    if (element.IsNullable)
                    {
                        WriteNullCheckBegin(arrayName, element);
                    }
                    else
                    {
                        if (mapping.TypeDesc.IsNullable)
                        {
                            ilg.Ldloc(ilg.GetLocal(arrayName));
                            ilg.Load(null);
                            ilg.If(Cmp.NotEqualTo);
                        }
                    }
                    WriteStartElement(name, ns, false);
                    WriteArrayItems(mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, arrayName, null);
                    WriteEndElement();
                    if (element.IsNullable)
                    {
                        ilg.EndIf();
                    }
                    else
                    {
                        if (mapping.TypeDesc.IsNullable)
                        {
                            ilg.EndIf();
                        }
                    }
                    ilg.ExitScope();
                }
            }
            else if (element.Mapping is EnumMapping)
            {
                WritePrimitive("WriteElementString", name, ns, element.Default, source, element.Mapping, false, true, element.IsNullable);
            }
            else if (element.Mapping is PrimitiveMapping)
            {
                PrimitiveMapping mapping = (PrimitiveMapping)element.Mapping;
                if (mapping.TypeDesc == QnameTypeDesc)
                    WriteQualifiedNameElement(name, ns, GetConvertedDefaultValue(source.Type, element.Default), source, element.IsNullable, mapping);
                else
                {
                    string suffixRaw = mapping.TypeDesc.XmlEncodingNotRequired ? "Raw" : "";
                    WritePrimitive(element.IsNullable ? ("WriteNullableStringLiteral" + suffixRaw) : ("WriteElementString" + suffixRaw),
                                   name, ns, GetConvertedDefaultValue(source.Type, element.Default), source, mapping, false, true, element.IsNullable);
                }
            }
            else if (element.Mapping is StructMapping)
            {
                StructMapping mapping = (StructMapping)element.Mapping;

                string methodName = ReferenceMapping(mapping);

#if DEBUG
                // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
                if (methodName == null) throw new InvalidOperationException(string.Format(ResXml.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace);
#endif
                List<Type> argTypes = new List<Type>();
                ilg.Ldarg(0);
                ilg.Ldstr(name);
                argTypes.Add(typeof(string));
                ilg.Ldstr(ns);
                argTypes.Add(typeof(string));
                source.Load(mapping.TypeDesc.Type);
                argTypes.Add(mapping.TypeDesc.Type);
                if (mapping.TypeDesc.IsNullable)
                {
                    ilg.Ldc(element.IsNullable);
                    argTypes.Add(typeof(Boolean));
                }
                ilg.Ldc(false);
                argTypes.Add(typeof(Boolean));
                MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder,
                    methodName,
                    CodeGenerator.PrivateMethodAttributes,
                    typeof(void),
                    argTypes.ToArray());
                ilg.Call(methodBuilder);
            }
            else if (element.Mapping is SpecialMapping)
            {
                SpecialMapping mapping = (SpecialMapping)element.Mapping;
                TypeDesc td = mapping.TypeDesc;
                string fullTypeName = td.CSharpName;


                if (element.Mapping is SerializableMapping)
                {
                    WriteElementCall("WriteSerializable", typeof(IXmlSerializable), source, name, ns, element.IsNullable, !element.Any);
                }
                else
                {
                    // XmlNode, XmlElement
                    Label ifLabel1 = ilg.DefineLabel();
                    Label ifLabel2 = ilg.DefineLabel();
                    source.Load(null);
                    ilg.IsInst(typeof(XmlNode));
                    ilg.Brtrue(ifLabel1);
                    source.Load(null);
                    ilg.Load(null);
                    ilg.Ceq();
                    ilg.Br(ifLabel2);
                    ilg.MarkLabel(ifLabel1);
                    ilg.Ldc(true);
                    ilg.MarkLabel(ifLabel2);
                    ilg.If();

                    WriteElementCall("WriteElementLiteral", typeof(XmlNode), source, name, ns, element.IsNullable, element.Any);

                    ilg.Else();

                    MethodInfo XmlSerializationWriter_CreateInvalidAnyTypeException = typeof(XmlSerializationWriter).GetMethod(
                        "CreateInvalidAnyTypeException",
                        CodeGenerator.InstanceBindingFlags,
                        null,
                        new Type[] { typeof(Object) },
                        null
                        );
                    ilg.Ldarg(0);
                    source.Load(null);
                    ilg.Call(XmlSerializationWriter_CreateInvalidAnyTypeException);
                    ilg.Throw();

                    ilg.EndIf();
                }
            }
            else
            {
                throw new InvalidOperationException(ResXml.XmlInternalError);
            }
        }