File: FrameworkFork\Microsoft.Xml\Xml\Serialization\XmlSerializationWriter.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace Microsoft.Xml.Serialization
{
    using System;
    using System.IO;
    using System.Collections;
    using System.Reflection;
    using System.Reflection.Emit;
    using Microsoft.Xml.Schema;
    using System.ComponentModel;
    using System.Diagnostics;
    using Microsoft.CodeDom.Compiler;
    using System.Globalization;
    using System.Text;
    using System.Threading;
    // using System.Security.Permissions;
    using System.Runtime.Versioning;
 
    /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter"]/*' />
    ///<internalonly/>
    public abstract class XmlSerializationWriter : XmlSerializationGeneratedCode
    {
        private XmlWriter _w;
        private XmlSerializerNamespaces _namespaces;
        private int _tempNamespacePrefix;
        private Hashtable _usedPrefixes;
        private Hashtable _references;
        private string _idBase;
        private int _nextId;
        private Hashtable _typeEntries;
        private ArrayList _referencesToWrite;
        private Hashtable _objectsInUse;
        private string _aliasBase = "q";
        private bool _soap12;
        private bool _escapeName = true;
 
        // this method must be called before any generated serialization methods are called
        internal void Init(XmlWriter w, XmlSerializerNamespaces namespaces, string encodingStyle, string idBase, TempAssembly tempAssembly)
        {
            _w = w;
            _namespaces = namespaces;
            _soap12 = (encodingStyle == Soap12.Encoding);
            _idBase = idBase;
            Init(tempAssembly);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.EscapeName"]/*' />
        protected bool EscapeName
        {
            get
            {
                return _escapeName;
            }
            set
            {
                _escapeName = value;
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.Writer"]/*' />
        protected XmlWriter Writer
        {
            get
            {
                return _w;
            }
            set
            {
                _w = value;
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.Namespaces"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected ArrayList Namespaces
        {
            get
            {
                return _namespaces == null ? null : _namespaces.NamespaceList;
            }
            set
            {
                if (value == null)
                {
                    _namespaces = null;
                }
                else
                {
                    XmlQualifiedName[] qnames = (XmlQualifiedName[])value.ToArray(typeof(XmlQualifiedName));
                    _namespaces = new XmlSerializerNamespaces(qnames);
                }
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromByteArrayBase64"]/*' />
        protected static byte[] FromByteArrayBase64(byte[] value)
        {
            // Unlike other "From" functions that one is just a place holder for automatic code generation.
            // The reason is performance and memory consumption for (potentially) big 64base-encoded chunks
            // And it is assumed that the caller generates the code that will distinguish between byte[] and string return types
            //
            return value;
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.ResolveDynamicAssembly"]/*' />
        ///<internalonly/>
        protected static Assembly ResolveDynamicAssembly(string assemblyFullName)
        {
            return DynamicAssemblies.Get(assemblyFullName);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromByteArrayHex"]/*' />
        protected static string FromByteArrayHex(byte[] value)
        {
            return XmlCustomFormatter.FromByteArrayHex(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromDateTime"]/*' />
        protected static string FromDateTime(DateTime value)
        {
            return XmlCustomFormatter.FromDateTime(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromDate"]/*' />
        protected static string FromDate(DateTime value)
        {
            return XmlCustomFormatter.FromDate(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromTime"]/*' />
        protected static string FromTime(DateTime value)
        {
            return XmlCustomFormatter.FromTime(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromChar"]/*' />
        protected static string FromChar(char value)
        {
            return XmlCustomFormatter.FromChar(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromEnum"]/*' />
        protected static string FromEnum(long value, string[] values, long[] ids)
        {
            return XmlCustomFormatter.FromEnum(value, values, ids, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromEnum1"]/*' />
        protected static string FromEnum(long value, string[] values, long[] ids, string typeName)
        {
            return XmlCustomFormatter.FromEnum(value, values, ids, typeName);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlName"]/*' />
        protected static string FromXmlName(string name)
        {
            return XmlCustomFormatter.FromXmlName(name);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNCName"]/*' />
        protected static string FromXmlNCName(string ncName)
        {
            return XmlCustomFormatter.FromXmlNCName(ncName);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNmToken"]/*' />
        protected static string FromXmlNmToken(string nmToken)
        {
            return XmlCustomFormatter.FromXmlNmToken(nmToken);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlNmTokens"]/*' />
        protected static string FromXmlNmTokens(string nmTokens)
        {
            return XmlCustomFormatter.FromXmlNmTokens(nmTokens);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXsiType"]/*' />
        protected void WriteXsiType(string name, string ns)
        {
            WriteAttribute("type", XmlSchema.InstanceNamespace, GetQualifiedName(name, ns));
        }
 
        private XmlQualifiedName GetPrimitiveTypeName(Type type)
        {
            return GetPrimitiveTypeName(type, true);
        }
 
        private XmlQualifiedName GetPrimitiveTypeName(Type type, bool throwIfUnknown)
        {
            XmlQualifiedName qname = GetPrimitiveTypeNameInternal(type);
            if (throwIfUnknown && qname == null)
                throw CreateUnknownTypeException(type);
            return qname;
        }
 
        internal static XmlQualifiedName GetPrimitiveTypeNameInternal(Type type)
        {
            string typeName;
            string typeNs = XmlSchema.Namespace;
 
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.String: typeName = "string"; break;
                case TypeCode.Int32: typeName = "int"; break;
                case TypeCode.Boolean: typeName = "boolean"; break;
                case TypeCode.Int16: typeName = "short"; break;
                case TypeCode.Int64: typeName = "long"; break;
                case TypeCode.Single: typeName = "float"; break;
                case TypeCode.Double: typeName = "double"; break;
                case TypeCode.Decimal: typeName = "decimal"; break;
                case TypeCode.DateTime: typeName = "dateTime"; break;
                case TypeCode.Byte: typeName = "unsignedByte"; break;
                case TypeCode.SByte: typeName = "byte"; break;
                case TypeCode.UInt16: typeName = "unsignedShort"; break;
                case TypeCode.UInt32: typeName = "unsignedInt"; break;
                case TypeCode.UInt64: typeName = "unsignedLong"; break;
                case TypeCode.Char:
                    typeName = "char";
                    typeNs = UrtTypes.Namespace;
                    break;
                default:
                    if (type == typeof(XmlQualifiedName)) typeName = "QName";
                    else if (type == typeof(byte[])) typeName = "base64Binary";
                    else if (type == typeof(Guid))
                    {
                        typeName = "guid";
                        typeNs = UrtTypes.Namespace;
                    }
                    else if (type == typeof(XmlNode[]))
                    {
                        typeName = Soap.UrType;
                    }
                    else
                        return null;
                    break;
            }
            return new XmlQualifiedName(typeName, typeNs);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteTypedPrimitive"]/*' />
        protected void WriteTypedPrimitive(string name, string ns, object o, bool xsiType)
        {
            string value = null;
            string type;
            string typeNs = XmlSchema.Namespace;
            bool writeRaw = true;
            bool writeDirect = false;
            Type t = o.GetType();
            bool wroteStartElement = false;
 
            switch (Type.GetTypeCode(t))
            {
                case TypeCode.String:
                    value = (string)o;
                    type = "string";
                    writeRaw = false;
                    break;
                case TypeCode.Int32:
                    value = XmlConvert.ToString((int)o);
                    type = "int";
                    break;
                case TypeCode.Boolean:
                    value = XmlConvert.ToString((bool)o);
                    type = "boolean";
                    break;
                case TypeCode.Int16:
                    value = XmlConvert.ToString((short)o);
                    type = "short";
                    break;
                case TypeCode.Int64:
                    value = XmlConvert.ToString((long)o);
                    type = "long";
                    break;
                case TypeCode.Single:
                    value = XmlConvert.ToString((float)o);
                    type = "float";
                    break;
                case TypeCode.Double:
                    value = XmlConvert.ToString((double)o);
                    type = "double";
                    break;
                case TypeCode.Decimal:
                    value = XmlConvert.ToString((decimal)o);
                    type = "decimal";
                    break;
                case TypeCode.DateTime:
                    value = FromDateTime((DateTime)o);
                    type = "dateTime";
                    break;
                case TypeCode.Char:
                    value = FromChar((char)o);
                    type = "char";
                    typeNs = UrtTypes.Namespace;
                    break;
                case TypeCode.Byte:
                    value = XmlConvert.ToString((byte)o);
                    type = "unsignedByte";
                    break;
                case TypeCode.SByte:
                    value = XmlConvert.ToString((sbyte)o);
                    type = "byte";
                    break;
                case TypeCode.UInt16:
                    value = XmlConvert.ToString((UInt16)o);
                    type = "unsignedShort";
                    break;
                case TypeCode.UInt32:
                    value = XmlConvert.ToString((UInt32)o);
                    type = "unsignedInt";
                    break;
                case TypeCode.UInt64:
                    value = XmlConvert.ToString((UInt64)o);
                    type = "unsignedLong";
                    break;
 
                default:
                    if (t == typeof(XmlQualifiedName))
                    {
                        type = "QName";
                        // need to write start element ahead of time to establish context
                        // for ns definitions by FromXmlQualifiedName
                        wroteStartElement = true;
                        if (name == null)
                            _w.WriteStartElement(type, typeNs);
                        else
                            _w.WriteStartElement(name, ns);
                        value = FromXmlQualifiedName((XmlQualifiedName)o, false);
                    }
                    else if (t == typeof(byte[]))
                    {
                        value = String.Empty;
                        writeDirect = true;
                        type = "base64Binary";
                    }
                    else if (t == typeof(Guid))
                    {
                        value = XmlConvert.ToString((Guid)o);
                        type = "guid";
                        typeNs = UrtTypes.Namespace;
                    }
                    else if (typeof(XmlNode[]).IsAssignableFrom(t))
                    {
                        if (name == null)
                            _w.WriteStartElement(Soap.UrType, XmlSchema.Namespace);
                        else
                            _w.WriteStartElement(name, ns);
 
                        XmlNode[] xmlNodes = (XmlNode[])o;
                        for (int i = 0; i < xmlNodes.Length; i++)
                        {
                            if (xmlNodes[i] == null)
                                continue;
                            xmlNodes[i].WriteTo(_w);
                        }
                        _w.WriteEndElement();
                        return;
                    }
                    else
                        throw CreateUnknownTypeException(t);
                    break;
            }
            if (!wroteStartElement)
            {
                if (name == null)
                    _w.WriteStartElement(type, typeNs);
                else
                    _w.WriteStartElement(name, ns);
            }
 
            if (xsiType) WriteXsiType(type, typeNs);
 
            if (value == null)
            {
                _w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
            }
            else if (writeDirect)
            {
                // only one type currently writes directly to XML stream
                XmlCustomFormatter.WriteArrayBase64(_w, (byte[])o, 0, ((byte[])o).Length);
            }
            else if (writeRaw)
            {
                _w.WriteRaw(value);
            }
            else
                _w.WriteString(value);
            _w.WriteEndElement();
        }
 
        private string GetQualifiedName(string name, string ns)
        {
            if (ns == null || ns.Length == 0) return name;
            string prefix = _w.LookupPrefix(ns);
            if (prefix == null)
            {
                if (ns == XmlReservedNs.NsXml)
                {
                    prefix = "xml";
                }
                else
                {
                    prefix = NextPrefix();
                    WriteAttribute("xmlns", prefix, null, ns);
                }
            }
            else if (prefix.Length == 0)
            {
                return name;
            }
            return prefix + ":" + name;
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlQualifiedName"]/*' />
        protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName)
        {
            return FromXmlQualifiedName(xmlQualifiedName, true);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.FromXmlQualifiedName"]/*' />
        protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName, bool ignoreEmpty)
        {
            if (xmlQualifiedName == null) return null;
            if (xmlQualifiedName.IsEmpty && ignoreEmpty) return null;
            return GetQualifiedName(EscapeName ? XmlConvert.EncodeLocalName(xmlQualifiedName.Name) : xmlQualifiedName.Name, xmlQualifiedName.Namespace);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement"]/*' />
        protected void WriteStartElement(string name)
        {
            WriteStartElement(name, null, null, false, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement1"]/*' />
        protected void WriteStartElement(string name, string ns)
        {
            WriteStartElement(name, ns, null, false, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement4"]/*' />
        protected void WriteStartElement(string name, string ns, bool writePrefixed)
        {
            WriteStartElement(name, ns, null, writePrefixed, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement2"]/*' />
        protected void WriteStartElement(string name, string ns, object o)
        {
            WriteStartElement(name, ns, o, false, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement3"]/*' />
        protected void WriteStartElement(string name, string ns, object o, bool writePrefixed)
        {
            WriteStartElement(name, ns, o, writePrefixed, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartElement5"]/*' />
        protected void WriteStartElement(string name, string ns, object o, bool writePrefixed, XmlSerializerNamespaces xmlns)
        {
            if (o != null && _objectsInUse != null)
            {
                if (_objectsInUse.ContainsKey(o)) throw new InvalidOperationException(string.Format(ResXml.XmlCircularReference, o.GetType().FullName));
                _objectsInUse.Add(o, o);
            }
 
            string prefix = null;
            bool needEmptyDefaultNamespace = false;
            if (_namespaces != null)
            {
                foreach (string alias in _namespaces.Namespaces.Keys)
                {
                    string aliasNs = (string)_namespaces.Namespaces[alias];
 
                    if (alias.Length > 0 && aliasNs == ns)
                        prefix = alias;
                    if (alias.Length == 0)
                    {
                        if (aliasNs == null || aliasNs.Length == 0)
                            needEmptyDefaultNamespace = true;
                        if (ns != aliasNs)
                            writePrefixed = true;
                    }
                }
                _usedPrefixes = ListUsedPrefixes(_namespaces.Namespaces, _aliasBase);
            }
            if (writePrefixed && prefix == null && ns != null && ns.Length > 0)
            {
                prefix = _w.LookupPrefix(ns);
                if (prefix == null || prefix.Length == 0)
                {
                    prefix = NextPrefix();
                }
            }
            if (prefix == null && xmlns != null)
            {
                prefix = xmlns.LookupPrefix(ns);
            }
            if (needEmptyDefaultNamespace && prefix == null && ns != null && ns.Length != 0)
                prefix = NextPrefix();
            _w.WriteStartElement(prefix, name, ns);
            if (_namespaces != null)
            {
                foreach (string alias in _namespaces.Namespaces.Keys)
                {
                    string aliasNs = (string)_namespaces.Namespaces[alias];
                    if (alias.Length == 0 && (aliasNs == null || aliasNs.Length == 0))
                        continue;
                    if (aliasNs == null || aliasNs.Length == 0)
                    {
                        if (alias.Length > 0)
                            throw new InvalidOperationException(string.Format(ResXml.XmlInvalidXmlns, alias));
                        WriteAttribute("xmlns", alias, null, aliasNs);
                    }
                    else
                    {
                        if (_w.LookupPrefix(aliasNs) == null)
                        {
                            // write the default namespace declaration only if we have not written it already, over wise we just ignore one provided by the user
                            if (prefix == null && alias.Length == 0)
                                break;
                            WriteAttribute("xmlns", alias, null, aliasNs);
                        }
                    }
                }
            }
            WriteNamespaceDeclarations(xmlns);
        }
 
        private Hashtable ListUsedPrefixes(Hashtable nsList, string prefix)
        {
            Hashtable qnIndexes = new Hashtable();
            int prefixLength = prefix.Length;
            const string MaxInt32 = "2147483647";
            foreach (string alias in _namespaces.Namespaces.Keys)
            {
                string name;
                if (alias.Length > prefixLength)
                {
                    name = alias;
                    int nameLength = name.Length;
                    if (name.Length > prefixLength && name.Length <= prefixLength + MaxInt32.Length && name.StartsWith(prefix, StringComparison.Ordinal))
                    {
                        bool numeric = true;
                        for (int j = prefixLength; j < name.Length; j++)
                        {
                            if (!Char.IsDigit(name, j))
                            {
                                numeric = false;
                                break;
                            }
                        }
                        if (numeric)
                        {
                            Int64 index = Int64.Parse(name.Substring(prefixLength), CultureInfo.InvariantCulture);
                            if (index <= Int32.MaxValue)
                            {
                                Int32 newIndex = (Int32)index;
                                if (!qnIndexes.ContainsKey(newIndex))
                                {
                                    qnIndexes.Add(newIndex, newIndex);
                                }
                            }
                        }
                    }
                }
            }
            if (qnIndexes.Count > 0)
            {
                return qnIndexes;
            }
            return null;
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagEncoded"]/*' />
        protected void WriteNullTagEncoded(string name)
        {
            WriteNullTagEncoded(name, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagEncoded1"]/*' />
        protected void WriteNullTagEncoded(string name, string ns)
        {
            if (name == null || name.Length == 0)
                return;
            WriteStartElement(name, ns, null, true);
            _w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTagLiteral"]/*' />
        protected void WriteNullTagLiteral(string name)
        {
            WriteNullTagLiteral(name, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullTag1"]/*' />
        protected void WriteNullTagLiteral(string name, string ns)
        {
            if (name == null || name.Length == 0)
                return;
            WriteStartElement(name, ns, null, false);
            _w.WriteAttributeString("nil", XmlSchema.InstanceNamespace, "true");
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEmptyTag"]/*' />
        protected void WriteEmptyTag(string name)
        {
            WriteEmptyTag(name, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEmptyTag1"]/*' />
        protected void WriteEmptyTag(string name, string ns)
        {
            if (name == null || name.Length == 0)
                return;
            WriteStartElement(name, ns, null, false);
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEndElement"]/*' />
        protected void WriteEndElement()
        {
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteEndElement1"]/*' />
        protected void WriteEndElement(object o)
        {
            _w.WriteEndElement();
 
            if (o != null && _objectsInUse != null)
            {
#if DEBUG
                // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
                if (!_objectsInUse.ContainsKey(o)) throw new InvalidOperationException(string.Format(ResXml.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName));
#endif
 
                _objectsInUse.Remove(o);
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteSerializable"]/*' />
        protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable)
        {
            WriteSerializable(serializable, name, ns, isNullable, true);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteSerializable1"]/*' />
        protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable, bool wrapped)
        {
            if (serializable == null)
            {
                if (isNullable) WriteNullTagLiteral(name, ns);
                return;
            }
            if (wrapped)
            {
                _w.WriteStartElement(name, ns);
            }
            serializable.WriteXml(_w);
            if (wrapped)
            {
                _w.WriteEndElement();
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncoded"]/*' />
        protected void WriteNullableStringEncoded(string name, string ns, string value, XmlQualifiedName xsiType)
        {
            if (value == null)
                WriteNullTagEncoded(name, ns);
            else
                WriteElementString(name, ns, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteral"]/*' />
        protected void WriteNullableStringLiteral(string name, string ns, string value)
        {
            if (value == null)
                WriteNullTagLiteral(name, ns);
            else
                WriteElementString(name, ns, value, null);
        }
 
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncodedRaw"]/*' />
        protected void WriteNullableStringEncodedRaw(string name, string ns, string value, XmlQualifiedName xsiType)
        {
            if (value == null)
                WriteNullTagEncoded(name, ns);
            else
                WriteElementStringRaw(name, ns, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringEncodedRaw1"]/*' />
        protected void WriteNullableStringEncodedRaw(string name, string ns, byte[] value, XmlQualifiedName xsiType)
        {
            if (value == null)
                WriteNullTagEncoded(name, ns);
            else
                WriteElementStringRaw(name, ns, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteralRaw"]/*' />
        protected void WriteNullableStringLiteralRaw(string name, string ns, string value)
        {
            if (value == null)
                WriteNullTagLiteral(name, ns);
            else
                WriteElementStringRaw(name, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableStringLiteralRaw1"]/*' />
        protected void WriteNullableStringLiteralRaw(string name, string ns, byte[] value)
        {
            if (value == null)
                WriteNullTagLiteral(name, ns);
            else
                WriteElementStringRaw(name, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableQualifiedNameEncoded"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected void WriteNullableQualifiedNameEncoded(string name, string ns, XmlQualifiedName value, XmlQualifiedName xsiType)
        {
            if (value == null)
                WriteNullTagEncoded(name, ns);
            else
                WriteElementQualifiedName(name, ns, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNullableQualifiedNameLiteral"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected void WriteNullableQualifiedNameLiteral(string name, string ns, XmlQualifiedName value)
        {
            if (value == null)
                WriteNullTagLiteral(name, ns);
            else
                WriteElementQualifiedName(name, ns, value, null);
        }
 
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementEncoded"]/*' />
        protected void WriteElementEncoded(XmlNode node, string name, string ns, bool isNullable, bool any)
        {
            if (node == null)
            {
                if (isNullable) WriteNullTagEncoded(name, ns);
                return;
            }
            WriteElement(node, name, ns, isNullable, any);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementLiteral"]/*' />
        protected void WriteElementLiteral(XmlNode node, string name, string ns, bool isNullable, bool any)
        {
            if (node == null)
            {
                if (isNullable) WriteNullTagLiteral(name, ns);
                return;
            }
            WriteElement(node, name, ns, isNullable, any);
        }
 
        private void WriteElement(XmlNode node, string name, string ns, bool isNullable, bool any)
        {
            if (typeof(XmlAttribute).IsAssignableFrom(node.GetType()))
                throw new InvalidOperationException(ResXml.XmlNoAttributeHere);
            if (node is XmlDocument)
            {
                node = ((XmlDocument)node).DocumentElement;
                if (node == null)
                {
                    if (isNullable) WriteNullTagEncoded(name, ns);
                    return;
                }
            }
            if (any)
            {
                if (node is XmlElement && name != null && name.Length > 0)
                {
                    // need to check against schema
                    if (node.LocalName != name || node.NamespaceURI != ns)
                        throw new InvalidOperationException(string.Format(ResXml.XmlElementNameMismatch, node.LocalName, node.NamespaceURI, name, ns));
                }
            }
            else
                _w.WriteStartElement(name, ns);
 
            node.WriteTo(_w);
 
            if (!any)
                _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownTypeException"]/*' />
        protected Exception CreateUnknownTypeException(object o)
        {
            return CreateUnknownTypeException(o.GetType());
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownTypeException1"]/*' />
        protected Exception CreateUnknownTypeException(Type type)
        {
            if (typeof(IXmlSerializable).IsAssignableFrom(type)) return new InvalidOperationException(string.Format(ResXml.XmlInvalidSerializable, type.FullName));
            TypeDesc typeDesc = new TypeScope().GetTypeDesc(type);
            if (!typeDesc.IsStructLike) return new InvalidOperationException(string.Format(ResXml.XmlInvalidUseOfType, type.FullName));
            return new InvalidOperationException(string.Format(ResXml.XmlUnxpectedType, type.FullName));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateMismatchChoiceException"]/*' />
        protected Exception CreateMismatchChoiceException(string value, string elementName, string enumValue)
        {
            // Value of {0} mismatches the type of {1}, you need to set it to {2}.
            return new InvalidOperationException(string.Format(ResXml.XmlChoiceMismatchChoiceException, elementName, value, enumValue));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateUnknownAnyElementException"]/*' />
        protected Exception CreateUnknownAnyElementException(string name, string ns)
        {
            return new InvalidOperationException(string.Format(ResXml.XmlUnknownAnyElement, name, ns));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidChoiceIdentifierValueException"]/*' />
        protected Exception CreateInvalidChoiceIdentifierValueException(string type, string identifier)
        {
            return new InvalidOperationException(string.Format(ResXml.XmlInvalidChoiceIdentifierValue, type, identifier));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateChoiceIdentifierValueException"]/*' />
        protected Exception CreateChoiceIdentifierValueException(string value, string identifier, string name, string ns)
        {
            // XmlChoiceIdentifierMismatch=Value '{0}' of the choice identifier '{1}' does not match element '{2}' from namespace '{3}'.
            return new InvalidOperationException(string.Format(ResXml.XmlChoiceIdentifierMismatch, value, identifier, name, ns));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidEnumValueException"]/*' />
        protected Exception CreateInvalidEnumValueException(object value, string typeName)
        {
            return new InvalidOperationException(string.Format(ResXml.XmlUnknownConstant, value, typeName));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidAnyTypeException"]/*' />
        protected Exception CreateInvalidAnyTypeException(object o)
        {
            return CreateInvalidAnyTypeException(o.GetType());
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.CreateInvalidAnyTypeException1"]/*' />
        protected Exception CreateInvalidAnyTypeException(Type type)
        {
            return new InvalidOperationException(string.Format(ResXml.XmlIllegalAnyElement, type.FullName));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencingElement"]/*' />
        protected void WriteReferencingElement(string n, string ns, object o)
        {
            WriteReferencingElement(n, ns, o, false);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencingElement1"]/*' />
        protected void WriteReferencingElement(string n, string ns, object o, bool isNullable)
        {
            if (o == null)
            {
                if (isNullable) WriteNullTagEncoded(n, ns);
                return;
            }
            WriteStartElement(n, ns, null, true);
            if (_soap12)
                _w.WriteAttributeString("ref", Soap12.Encoding, GetId(o, true));
            else
                _w.WriteAttributeString("href", "#" + GetId(o, true));
            _w.WriteEndElement();
        }
 
        private bool IsIdDefined(object o)
        {
            if (_references != null) return _references.Contains(o);
            else return false;
        }
 
        private string GetId(object o, bool addToReferencesList)
        {
            if (_references == null)
            {
                _references = new Hashtable();
                _referencesToWrite = new ArrayList();
            }
            string id = (string)_references[o];
            if (id == null)
            {
                id = _idBase + "id" + (++_nextId).ToString();
                _references.Add(o, id);
                if (addToReferencesList) _referencesToWrite.Add(o);
            }
            return id;
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteId"]/*' />
        protected void WriteId(object o)
        {
            WriteId(o, true);
        }
 
        private void WriteId(object o, bool addToReferencesList)
        {
            if (_soap12)
                _w.WriteAttributeString("id", Soap12.Encoding, GetId(o, addToReferencesList));
            else
                _w.WriteAttributeString("id", GetId(o, addToReferencesList));
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXmlAttribute1"]/*' />
        protected void WriteXmlAttribute(XmlNode node)
        {
            WriteXmlAttribute(node, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteXmlAttribute2"]/*' />
        protected void WriteXmlAttribute(XmlNode node, object container)
        {
            XmlAttribute attr = node as XmlAttribute;
            if (attr == null) throw new InvalidOperationException(ResXml.XmlNeedAttributeHere);
            if (attr.Value != null)
            {
                if (attr.NamespaceURI == Wsdl.Namespace && attr.LocalName == Wsdl.ArrayType)
                {
                    string dims;
                    XmlQualifiedName qname = TypeScope.ParseWsdlArrayType(attr.Value, out dims, (container is XmlSchemaObject) ? (XmlSchemaObject)container : null);
 
                    string value = FromXmlQualifiedName(qname, true) + dims;
 
                    //<xsd:attribute xmlns:q3="s0" wsdl:arrayType="q3:FoosBase[]" xmlns:q4="http://schemas.xmlsoap.org/soap/encoding/" ref="q4:arrayType" />
                    WriteAttribute(Wsdl.ArrayType, Wsdl.Namespace, value);
                }
                else
                {
                    WriteAttribute(attr.Name, attr.NamespaceURI, attr.Value);
                }
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute"]/*' />
        protected void WriteAttribute(string localName, string ns, string value)
        {
            if (value == null) return;
            if (localName == "xmlns" || localName.StartsWith("xmlns:", StringComparison.Ordinal))
            {
                ;
            }
            else
            {
                int colon = localName.IndexOf(':');
                if (colon < 0)
                {
                    if (ns == XmlReservedNs.NsXml)
                    {
                        string prefix = _w.LookupPrefix(ns);
                        if (prefix == null || prefix.Length == 0)
                            prefix = "xml";
                        _w.WriteAttributeString(prefix, localName, ns, value);
                    }
                    else
                    {
                        _w.WriteAttributeString(localName, ns, value);
                    }
                }
                else
                {
                    string prefix = localName.Substring(0, colon);
                    _w.WriteAttributeString(prefix, localName.Substring(colon + 1), ns, value);
                }
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute0"]/*' />
        protected void WriteAttribute(string localName, string ns, byte[] value)
        {
            if (value == null) return;
            if (localName == "xmlns" || localName.StartsWith("xmlns:", StringComparison.Ordinal))
            {
                ;
            }
            else
            {
                int colon = localName.IndexOf(':');
                if (colon < 0)
                {
                    if (ns == XmlReservedNs.NsXml)
                    {
                        string prefix = _w.LookupPrefix(ns);
                        if (prefix == null || prefix.Length == 0)
                            prefix = "xml";
                        _w.WriteStartAttribute("xml", localName, ns);
                    }
                    else
                    {
                        _w.WriteStartAttribute(null, localName, ns);
                    }
                }
                else
                {
                    string prefix = localName.Substring(0, colon);
                    prefix = _w.LookupPrefix(ns);
                    _w.WriteStartAttribute(prefix, localName.Substring(colon + 1), ns);
                }
                XmlCustomFormatter.WriteArrayBase64(_w, value, 0, value.Length);
                _w.WriteEndAttribute();
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute1"]/*' />
        protected void WriteAttribute(string localName, string value)
        {
            if (value == null) return;
            _w.WriteAttributeString(localName, null, value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute01"]/*' />
        protected void WriteAttribute(string localName, byte[] value)
        {
            if (value == null) return;
 
            _w.WriteStartAttribute(null, localName, (string)null);
            XmlCustomFormatter.WriteArrayBase64(_w, value, 0, value.Length);
            _w.WriteEndAttribute();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteAttribute2"]/*' />
        protected void WriteAttribute(string prefix, string localName, string ns, string value)
        {
            if (value == null) return;
            _w.WriteAttributeString(prefix, localName, null, value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteValue"]/*' />
        protected void WriteValue(string value)
        {
            if (value == null) return;
            _w.WriteString(value);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteValue01"]/*' />
        protected void WriteValue(byte[] value)
        {
            if (value == null) return;
            XmlCustomFormatter.WriteArrayBase64(_w, value, 0, value.Length);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteStartDocument"]/*' />
        protected void WriteStartDocument()
        {
            if (_w.WriteState == WriteState.Start)
            {
                _w.WriteStartDocument();
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString"]/*' />
        protected void WriteElementString(String localName, String value)
        {
            WriteElementString(localName, null, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString1"]/*' />
        protected void WriteElementString(String localName, String ns, String value)
        {
            WriteElementString(localName, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString2"]/*' />
        protected void WriteElementString(String localName, String value, XmlQualifiedName xsiType)
        {
            WriteElementString(localName, null, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementString3"]/*' />
        protected void WriteElementString(String localName, String ns, String value, XmlQualifiedName xsiType)
        {
            if (value == null) return;
            if (xsiType == null)
                _w.WriteElementString(localName, ns, value);
            else
            {
                _w.WriteStartElement(localName, ns);
                WriteXsiType(xsiType.Name, xsiType.Namespace);
                _w.WriteString(value);
                _w.WriteEndElement();
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw"]/*' />
        protected void WriteElementStringRaw(String localName, String value)
        {
            WriteElementStringRaw(localName, null, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw0"]/*' />
        protected void WriteElementStringRaw(String localName, byte[] value)
        {
            WriteElementStringRaw(localName, null, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw1"]/*' />
        protected void WriteElementStringRaw(String localName, String ns, String value)
        {
            WriteElementStringRaw(localName, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw01"]/*' />
        protected void WriteElementStringRaw(String localName, String ns, byte[] value)
        {
            WriteElementStringRaw(localName, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw2"]/*' />
        protected void WriteElementStringRaw(String localName, String value, XmlQualifiedName xsiType)
        {
            WriteElementStringRaw(localName, null, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw02"]/*' />
        protected void WriteElementStringRaw(String localName, byte[] value, XmlQualifiedName xsiType)
        {
            WriteElementStringRaw(localName, null, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw3"]/*' />
        protected void WriteElementStringRaw(String localName, String ns, String value, XmlQualifiedName xsiType)
        {
            if (value == null) return;
            _w.WriteStartElement(localName, ns);
            if (xsiType != null)
                WriteXsiType(xsiType.Name, xsiType.Namespace);
            _w.WriteRaw(value);
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementStringRaw03"]/*' />
        protected void WriteElementStringRaw(String localName, String ns, byte[] value, XmlQualifiedName xsiType)
        {
            if (value == null) return;
            _w.WriteStartElement(localName, ns);
            if (xsiType != null)
                WriteXsiType(xsiType.Name, xsiType.Namespace);
            XmlCustomFormatter.WriteArrayBase64(_w, value, 0, value.Length);
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteRpcResult"]/*' />
        protected void WriteRpcResult(string name, string ns)
        {
            if (!_soap12) return;
            WriteElementQualifiedName(Soap12.RpcResult, Soap12.RpcNamespace, new XmlQualifiedName(name, ns), null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected void WriteElementQualifiedName(String localName, XmlQualifiedName value)
        {
            WriteElementQualifiedName(localName, null, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName1"]/*' />
        protected void WriteElementQualifiedName(string localName, XmlQualifiedName value, XmlQualifiedName xsiType)
        {
            WriteElementQualifiedName(localName, null, value, xsiType);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName2"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        protected void WriteElementQualifiedName(String localName, String ns, XmlQualifiedName value)
        {
            WriteElementQualifiedName(localName, ns, value, null);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteElementQualifiedName3"]/*' />
        protected void WriteElementQualifiedName(string localName, string ns, XmlQualifiedName value, XmlQualifiedName xsiType)
        {
            if (value == null) return;
            if (value.Namespace == null || value.Namespace.Length == 0)
            {
                WriteStartElement(localName, ns, null, true);
                WriteAttribute("xmlns", "");
            }
            else
                _w.WriteStartElement(localName, ns);
            if (xsiType != null)
                WriteXsiType(xsiType.Name, xsiType.Namespace);
            _w.WriteString(FromXmlQualifiedName(value, false));
            _w.WriteEndElement();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.AddWriteCallback"]/*' />
        protected void AddWriteCallback(Type type, string typeName, string typeNs, XmlSerializationWriteCallback callback)
        {
            TypeEntry entry = new TypeEntry();
            entry.typeName = typeName;
            entry.typeNs = typeNs;
            entry.type = type;
            entry.callback = callback;
            _typeEntries[type] = entry;
        }
 
        private void WriteArray(string name, string ns, object o, Type type)
        {
            Type elementType = TypeScope.GetArrayElementType(type, null);
            string typeName;
            string typeNs;
 
            StringBuilder arrayDims = new StringBuilder();
            if (!_soap12)
            {
                while ((elementType.IsArray || typeof(IEnumerable).IsAssignableFrom(elementType)) && GetPrimitiveTypeName(elementType, false) == null)
                {
                    elementType = TypeScope.GetArrayElementType(elementType, null);
                    arrayDims.Append("[]");
                }
            }
 
            if (elementType == typeof(object))
            {
                typeName = Soap.UrType;
                typeNs = XmlSchema.Namespace;
            }
            else
            {
                TypeEntry entry = GetTypeEntry(elementType);
                if (entry != null)
                {
                    typeName = entry.typeName;
                    typeNs = entry.typeNs;
                }
                else if (_soap12)
                {
                    XmlQualifiedName qualName = GetPrimitiveTypeName(elementType, false);
                    if (qualName != null)
                    {
                        typeName = qualName.Name;
                        typeNs = qualName.Namespace;
                    }
                    else
                    {
                        Type elementBaseType = elementType.GetTypeInfo().BaseType;
                        while (elementBaseType != null)
                        {
                            entry = GetTypeEntry(elementBaseType);
                            if (entry != null) break;
                            elementBaseType = elementBaseType.GetTypeInfo().BaseType;
                        }
                        if (entry != null)
                        {
                            typeName = entry.typeName;
                            typeNs = entry.typeNs;
                        }
                        else
                        {
                            typeName = Soap.UrType;
                            typeNs = XmlSchema.Namespace;
                        }
                    }
                }
                else
                {
                    XmlQualifiedName qualName = GetPrimitiveTypeName(elementType);
                    typeName = qualName.Name;
                    typeNs = qualName.Namespace;
                }
            }
 
            if (arrayDims.Length > 0)
                typeName = typeName + arrayDims.ToString();
 
            if (_soap12 && name != null && name.Length > 0)
                WriteStartElement(name, ns, null, false);
            else
                WriteStartElement(Soap.Array, Soap.Encoding, null, true);
 
            WriteId(o, false);
 
            if (type.IsArray)
            {
                Array a = (Array)o;
                int arrayLength = a.Length;
                if (_soap12)
                {
                    _w.WriteAttributeString("itemType", Soap12.Encoding, GetQualifiedName(typeName, typeNs));
                    _w.WriteAttributeString("arraySize", Soap12.Encoding, arrayLength.ToString());
                }
                else
                {
                    _w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + "[" + arrayLength.ToString() + "]");
                }
                for (int i = 0; i < arrayLength; i++)
                {
                    WritePotentiallyReferencingElement("Item", "", a.GetValue(i), elementType, false, true);
                }
            }
            else
            {
#if DEBUG
                // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
                if (!typeof(IEnumerable).IsAssignableFrom(type)) throw new InvalidOperationException(string.Format(ResXml.XmlInternalErrorDetails, "not array like type " + type.FullName));
#endif
 
                int arrayLength = typeof(ICollection).IsAssignableFrom(type) ? ((ICollection)o).Count : -1;
                if (_soap12)
                {
                    _w.WriteAttributeString("itemType", Soap12.Encoding, GetQualifiedName(typeName, typeNs));
                    if (arrayLength >= 0)
                        _w.WriteAttributeString("arraySize", Soap12.Encoding, arrayLength.ToString());
                }
                else
                {
                    string brackets = arrayLength >= 0 ? "[" + arrayLength + "]" : "[]";
                    _w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + brackets);
                }
                IEnumerator e = ((IEnumerable)o).GetEnumerator();
                if (e != null)
                {
                    while (e.MoveNext())
                    {
                        WritePotentiallyReferencingElement("Item", "", e.Current, elementType, false, true);
                    }
                }
            }
            _w.WriteEndElement();
        }
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement"]/*' />
        protected void WritePotentiallyReferencingElement(string n, string ns, object o)
        {
            WritePotentiallyReferencingElement(n, ns, o, null, false, false);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement1"]/*' />
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType)
        {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, false, false);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement2"]/*' />
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference)
        {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, suppressReference, false);
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WritePotentiallyReferencingElement3"]/*' />
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference, bool isNullable)
        {
            if (o == null)
            {
                if (isNullable) WriteNullTagEncoded(n, ns);
                return;
            }
            Type t = o.GetType();
            if (Convert.GetTypeCode(o) == TypeCode.Object && !(o is Guid) && (t != typeof(XmlQualifiedName)) && !(o is XmlNode[]) && (t != typeof(byte[])))
            {
                if ((suppressReference || _soap12) && !IsIdDefined(o))
                {
                    WriteReferencedElement(n, ns, o, ambientType);
                }
                else
                {
                    if (n == null)
                    {
                        TypeEntry entry = GetTypeEntry(t);
                        WriteReferencingElement(entry.typeName, entry.typeNs, o, isNullable);
                    }
                    else
                        WriteReferencingElement(n, ns, o, isNullable);
                }
            }
            else
            {
                // Enums always write xsi:type, so don't write it again here.
                bool needXsiType = t != ambientType && !t.GetTypeInfo().IsEnum;
                TypeEntry entry = GetTypeEntry(t);
                if (entry != null)
                {
                    if (n == null)
                        WriteStartElement(entry.typeName, entry.typeNs, null, true);
                    else
                        WriteStartElement(n, ns, null, true);
 
                    if (needXsiType) WriteXsiType(entry.typeName, entry.typeNs);
                    entry.callback(o);
                    _w.WriteEndElement();
                }
                else
                {
                    WriteTypedPrimitive(n, ns, o, needXsiType);
                }
            }
        }
 
 
        private void WriteReferencedElement(object o, Type ambientType)
        {
            WriteReferencedElement(null, null, o, ambientType);
        }
 
        private void WriteReferencedElement(string name, string ns, object o, Type ambientType)
        {
            if (name == null) name = String.Empty;
            Type t = o.GetType();
            if (t.IsArray || typeof(IEnumerable).IsAssignableFrom(t))
            {
                WriteArray(name, ns, o, t);
            }
            else
            {
                TypeEntry entry = GetTypeEntry(t);
                if (entry == null) throw CreateUnknownTypeException(t);
                WriteStartElement(name.Length == 0 ? entry.typeName : name, ns == null ? entry.typeNs : ns, null, true);
                WriteId(o, false);
                if (ambientType != t) WriteXsiType(entry.typeName, entry.typeNs);
                entry.callback(o);
                _w.WriteEndElement();
            }
        }
 
        private TypeEntry GetTypeEntry(Type t)
        {
            if (_typeEntries == null)
            {
                _typeEntries = new Hashtable();
                InitCallbacks();
            }
            return (TypeEntry)_typeEntries[t];
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.InitCallbacks"]/*' />
        protected abstract void InitCallbacks();
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteReferencedElements"]/*' />
        protected void WriteReferencedElements()
        {
            if (_referencesToWrite == null) return;
 
            for (int i = 0; i < _referencesToWrite.Count; i++)
            {
                WriteReferencedElement(_referencesToWrite[i], null);
            }
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.TopLevelElement"]/*' />
        protected void TopLevelElement()
        {
            _objectsInUse = new Hashtable();
        }
 
        /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriter.WriteNamespaceDeclarations"]/*' />
        ///<internalonly/>
        protected void WriteNamespaceDeclarations(XmlSerializerNamespaces xmlns)
        {
            if (xmlns != null)
            {
                foreach (DictionaryEntry entry in xmlns.Namespaces)
                {
                    string prefix = (string)entry.Key;
                    string ns = (string)entry.Value;
                    if (_namespaces != null)
                    {
                        string oldNs = _namespaces.Namespaces[prefix] as string;
                        if (oldNs != null && oldNs != ns)
                        {
                            throw new InvalidOperationException(string.Format(ResXml.XmlDuplicateNs, prefix, ns));
                        }
                    }
                    string oldPrefix = (ns == null || ns.Length == 0) ? null : Writer.LookupPrefix(ns);
 
                    if (oldPrefix == null || oldPrefix != prefix)
                    {
                        WriteAttribute("xmlns", prefix, null, ns);
                    }
                }
            }
            _namespaces = null;
        }
 
        private string NextPrefix()
        {
            if (_usedPrefixes == null)
            {
                return _aliasBase + (++_tempNamespacePrefix);
            }
            while (_usedPrefixes.ContainsKey(++_tempNamespacePrefix)) {; }
            return _aliasBase + _tempNamespacePrefix;
        }
 
        internal class TypeEntry
        {
            internal XmlSerializationWriteCallback callback;
            internal string typeNs;
            internal string typeName;
            internal Type type;
        }
    }
 
 
    /// <include file='doc\XmlSerializationWriter.uex' path='docs/doc[@for="XmlSerializationWriteCallback"]/*' />
    ///<internalonly/>
    public delegate void XmlSerializationWriteCallback(object o);
 
    internal class XmlSerializationWriterCodeGen : XmlSerializationCodeGen
    {
        internal XmlSerializationWriterCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className) : base(writer, scopes, access, className)
        {
        }
 
        internal void GenerateBegin()
        {
            Writer.Write(Access);
            Writer.Write(" class ");
            Writer.Write(ClassName);
            Writer.Write(" : ");
            Writer.Write(typeof(XmlSerializationWriter).FullName);
            Writer.WriteLine(" {");
            Writer.Indent++;
 
            foreach (TypeScope scope in Scopes)
            {
                foreach (TypeMapping mapping in scope.TypeMappings)
                {
                    if (mapping is StructMapping || mapping is EnumMapping)
                    {
                        MethodNames.Add(mapping, NextMethodName(mapping.TypeDesc.Name));
                    }
                }
                RaCodeGen.WriteReflectionInit(scope);
            }
 
            // pre-generate write methods only for the encoded soap
            foreach (TypeScope scope in Scopes)
            {
                foreach (TypeMapping mapping in scope.TypeMappings)
                {
                    if (!mapping.IsSoap)
                        continue;
 
                    if (mapping is StructMapping)
                        WriteStructMethod((StructMapping)mapping);
                    else if (mapping is EnumMapping)
                        WriteEnumMethod((EnumMapping)mapping);
                }
            }
        }
 
        internal override void GenerateMethod(TypeMapping mapping)
        {
            if (GeneratedMethods.Contains(mapping))
                return;
 
            GeneratedMethods[mapping] = mapping;
            if (mapping is StructMapping)
            {
                WriteStructMethod((StructMapping)mapping);
            }
            else if (mapping is EnumMapping)
            {
                WriteEnumMethod((EnumMapping)mapping);
            }
        }
        internal void GenerateEnd()
        {
            GenerateReferencedMethods();
            GenerateInitCallbacksMethod();
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        internal string GenerateElement(XmlMapping xmlMapping)
        {
            if (!xmlMapping.IsWriteable)
                return null;
            if (!xmlMapping.GenerateSerializer)
                throw new ArgumentException(ResXml.XmlInternalError, "xmlMapping");
            if (xmlMapping is XmlTypeMapping)
                return GenerateTypeElement((XmlTypeMapping)xmlMapping);
            else if (xmlMapping is XmlMembersMapping)
                return GenerateMembersElement((XmlMembersMapping)xmlMapping);
            else
                throw new ArgumentException(ResXml.XmlInternalError, "xmlMapping");
        }
 
        private void GenerateInitCallbacksMethod()
        {
            Writer.WriteLine();
            Writer.WriteLine("protected override void InitCallbacks() {");
            Writer.Indent++;
 
            foreach (TypeScope scope in Scopes)
            {
                foreach (TypeMapping typeMapping in scope.TypeMappings)
                {
                    if (typeMapping.IsSoap &&
                        (typeMapping is StructMapping || typeMapping is EnumMapping) &&
                        !typeMapping.TypeDesc.IsRoot)
                    {
                        string methodName = (string)MethodNames[typeMapping];
                        Writer.Write("AddWriteCallback(");
                        Writer.Write(RaCodeGen.GetStringForTypeof(typeMapping.TypeDesc.CSharpName, typeMapping.TypeDesc.UseReflection));
                        Writer.Write(", ");
                        WriteQuotedCSharpString(typeMapping.TypeName);
                        Writer.Write(", ");
                        WriteQuotedCSharpString(typeMapping.Namespace);
                        Writer.Write(", new ");
                        Writer.Write(typeof(XmlSerializationWriteCallback).FullName);
                        Writer.Write("(this.");
                        Writer.Write(methodName);
                        Writer.WriteLine("));");
                    }
                }
            }
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        private void WriteQualifiedNameElement(string name, string ns, object defaultValue, string source, bool nullable, bool IsSoap, TypeMapping mapping)
        {
            bool hasDefault = defaultValue != null && defaultValue != DBNull.Value;
            if (hasDefault)
            {
                WriteCheckDefault(source, defaultValue, nullable);
                Writer.WriteLine(" {");
                Writer.Indent++;
            }
            string suffix = IsSoap ? "Encoded" : "Literal";
            Writer.Write(nullable ? ("WriteNullableQualifiedName" + suffix) : "WriteElementQualifiedName");
            Writer.Write("(");
            WriteQuotedCSharpString(name);
            if (ns != null)
            {
                Writer.Write(", ");
                WriteQuotedCSharpString(ns);
            }
            Writer.Write(", ");
            Writer.Write(source);
 
            if (IsSoap)
            {
                Writer.Write(", new Microsoft.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", ");
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")");
            }
 
            Writer.WriteLine(");");
 
            if (hasDefault)
            {
                Writer.Indent--;
                Writer.WriteLine("}");
            }
        }
 
        private void WriteEnumValue(EnumMapping mapping, string source)
        {
            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
 
            Writer.Write(methodName);
            Writer.Write("(");
            Writer.Write(source);
            Writer.Write(")");
        }
 
        private void WritePrimitiveValue(TypeDesc typeDesc, string source, bool isElement)
        {
            if (typeDesc == StringTypeDesc || typeDesc.FormatterName == "String")
            {
                Writer.Write(source);
            }
            else
            {
                if (!typeDesc.HasCustomFormatter)
                {
                    Writer.Write(typeof(XmlConvert).FullName);
                    Writer.Write(".ToString((");
                    Writer.Write(typeDesc.CSharpName);
                    Writer.Write(")");
                    Writer.Write(source);
                    Writer.Write(")");
                }
                else
                {
                    Writer.Write("From");
                    Writer.Write(typeDesc.FormatterName);
                    Writer.Write("(");
                    Writer.Write(source);
                    Writer.Write(")");
                }
            }
        }
 
        private void WritePrimitive(string method, string name, string ns, object defaultValue, string source, TypeMapping mapping, bool writeXsiType, bool isElement, bool isNullable)
        {
            TypeDesc typeDesc = mapping.TypeDesc;
            bool hasDefault = defaultValue != null && defaultValue != DBNull.Value && mapping.TypeDesc.HasDefaultSupport;
            if (hasDefault)
            {
                if (mapping is EnumMapping)
                {
#if DEBUG
                    // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
                    if (defaultValue.GetType() != typeof(string)) throw new InvalidOperationException(string.Format(ResXml.XmlInternalErrorDetails, name + " has invalid default type " + defaultValue.GetType().Name));
#endif
 
                    Writer.Write("if (");
                    if (mapping.TypeDesc.UseReflection)
                        Writer.Write(RaCodeGen.GetStringForEnumLongValue(source, mapping.TypeDesc.UseReflection));
                    else
                        Writer.Write(source);
                    Writer.Write(" != ");
                    if (((EnumMapping)mapping).IsFlags)
                    {
                        Writer.Write("(");
                        string[] values = ((string)defaultValue).Split(null);
                        for (int i = 0; i < values.Length; i++)
                        {
                            if (values[i] == null || values[i].Length == 0)
                                continue;
                            if (i > 0)
                                Writer.WriteLine(" | ");
                            Writer.Write(RaCodeGen.GetStringForEnumCompare((EnumMapping)mapping, values[i], mapping.TypeDesc.UseReflection));
                        }
                        Writer.Write(")");
                    }
                    else
                    {
                        Writer.Write(RaCodeGen.GetStringForEnumCompare((EnumMapping)mapping, (string)defaultValue, mapping.TypeDesc.UseReflection));
                    }
                    Writer.Write(")");
                }
                else
                {
                    WriteCheckDefault(source, defaultValue, isNullable);
                }
                Writer.WriteLine(" {");
                Writer.Indent++;
            }
            Writer.Write(method);
            Writer.Write("(");
            WriteQuotedCSharpString(name);
            if (ns != null)
            {
                Writer.Write(", ");
                WriteQuotedCSharpString(ns);
            }
            Writer.Write(", ");
 
            if (mapping is EnumMapping)
            {
                WriteEnumValue((EnumMapping)mapping, source);
            }
            else
            {
                WritePrimitiveValue(typeDesc, source, isElement);
            }
 
            if (writeXsiType)
            {
                Writer.Write(", new Microsoft.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", ");
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")");
            }
 
            Writer.WriteLine(");");
 
            if (hasDefault)
            {
                Writer.Indent--;
                Writer.WriteLine("}");
            }
        }
 
        private void WriteTag(string methodName, string name, string ns)
        {
            Writer.Write(methodName);
            Writer.Write("(");
            WriteQuotedCSharpString(name);
            Writer.Write(", ");
            if (ns == null)
            {
                Writer.Write("null");
            }
            else
            {
                WriteQuotedCSharpString(ns);
            }
            Writer.WriteLine(");");
        }
 
        private void WriteTag(string methodName, string name, string ns, bool writePrefixed)
        {
            Writer.Write(methodName);
            Writer.Write("(");
            WriteQuotedCSharpString(name);
            Writer.Write(", ");
            if (ns == null)
            {
                Writer.Write("null");
            }
            else
            {
                WriteQuotedCSharpString(ns);
            }
            Writer.Write(", null, ");
            if (writePrefixed)
                Writer.Write("true");
            else
                Writer.Write("false");
            Writer.WriteLine(");");
        }
 
        private void WriteStartElement(string name, string ns, bool writePrefixed)
        {
            WriteTag("WriteStartElement", name, ns, writePrefixed);
        }
 
        private void WriteEndElement()
        {
            Writer.WriteLine("WriteEndElement();");
        }
        private void WriteEndElement(string source)
        {
            Writer.Write("WriteEndElement(");
            Writer.Write(source);
            Writer.WriteLine(");");
        }
 
        private void WriteEncodedNullTag(string name, string ns)
        {
            WriteTag("WriteNullTagEncoded", name, ns);
        }
 
        private void WriteLiteralNullTag(string name, string ns)
        {
            WriteTag("WriteNullTagLiteral", name, ns);
        }
 
        private void WriteEmptyTag(string name, string ns)
        {
            WriteTag("WriteEmptyTag", name, ns);
        }
 
        private string GenerateMembersElement(XmlMembersMapping xmlMembersMapping)
        {
            ElementAccessor element = xmlMembersMapping.Accessor;
            MembersMapping mapping = (MembersMapping)element.Mapping;
            bool hasWrapperElement = mapping.HasWrapperElement;
            bool writeAccessors = mapping.WriteAccessors;
            bool isRpc = xmlMembersMapping.IsSoap && writeAccessors;
            string methodName = NextMethodName(element.Name);
            Writer.WriteLine();
            Writer.Write("public void ");
            Writer.Write(methodName);
            Writer.WriteLine("(object[] p) {");
            Writer.Indent++;
 
            Writer.WriteLine("WriteStartDocument();");
 
            if (!mapping.IsSoap)
            {
                Writer.WriteLine("TopLevelElement();");
            }
 
            // in the top-level method add check for the parameters length, 
            // because visual basic does not have a concept of an <out> parameter it uses <ByRef> instead
            // so sometime we think that we have more parameters then supplied
            Writer.WriteLine("int pLength = p.Length;");
 
            if (hasWrapperElement)
            {
                WriteStartElement(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""), mapping.IsSoap);
 
                int xmlnsMember = FindXmlnsIndex(mapping.Members);
                if (xmlnsMember >= 0)
                {
                    MemberMapping member = mapping.Members[xmlnsMember];
                    string source = "((" + typeof(XmlSerializerNamespaces).FullName + ")p[" + xmlnsMember.ToString() + "])";
 
                    Writer.Write("if (pLength > ");
                    Writer.Write(xmlnsMember.ToString());
                    Writer.WriteLine(") {");
                    Writer.Indent++;
                    WriteNamespaces(source);
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
 
                for (int i = 0; i < mapping.Members.Length; i++)
                {
                    MemberMapping member = mapping.Members[i];
 
                    if (member.Attribute != null && !member.Ignore)
                    {
                        string source = "p[" + i.ToString() + "]";
 
                        string specifiedSource = null;
                        int specifiedPosition = 0;
                        if (member.CheckSpecified != SpecifiedAccessor.None)
                        {
                            string memberNameSpecified = member.Name + "Specified";
                            for (int j = 0; j < mapping.Members.Length; j++)
                            {
                                if (mapping.Members[j].Name == memberNameSpecified)
                                {
                                    specifiedSource = "((bool) p[" + j.ToString() + "])";
                                    specifiedPosition = j;
                                    break;
                                }
                            }
                        }
 
                        Writer.Write("if (pLength > ");
                        Writer.Write(i.ToString());
                        Writer.WriteLine(") {");
                        Writer.Indent++;
 
                        if (specifiedSource != null)
                        {
                            Writer.Write("if (pLength <= ");
                            Writer.Write(specifiedPosition.ToString());
                            Writer.Write(" || ");
                            Writer.Write(specifiedSource);
                            Writer.WriteLine(") {");
                            Writer.Indent++;
                        }
 
                        WriteMember(source, member.Attribute, member.TypeDesc, "p");
 
                        if (specifiedSource != null)
                        {
                            Writer.Indent--;
                            Writer.WriteLine("}");
                        }
 
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                }
            }
 
            for (int i = 0; i < mapping.Members.Length; i++)
            {
                MemberMapping member = mapping.Members[i];
                if (member.Xmlns != null)
                    continue;
                if (member.Ignore)
                    continue;
 
                string specifiedSource = null;
                int specifiedPosition = 0;
                if (member.CheckSpecified != SpecifiedAccessor.None)
                {
                    string memberNameSpecified = member.Name + "Specified";
 
                    for (int j = 0; j < mapping.Members.Length; j++)
                    {
                        if (mapping.Members[j].Name == memberNameSpecified)
                        {
                            specifiedSource = "((bool) p[" + j.ToString() + "])";
                            specifiedPosition = j;
                            break;
                        }
                    }
                }
 
                Writer.Write("if (pLength > ");
                Writer.Write(i.ToString());
                Writer.WriteLine(") {");
                Writer.Indent++;
 
                if (specifiedSource != null)
                {
                    Writer.Write("if (pLength <= ");
                    Writer.Write(specifiedPosition.ToString());
                    Writer.Write(" || ");
                    Writer.Write(specifiedSource);
                    Writer.WriteLine(") {");
                    Writer.Indent++;
                }
 
                string source = "p[" + i.ToString() + "]";
                string enumSource = null;
                if (member.ChoiceIdentifier != null)
                {
                    for (int j = 0; j < mapping.Members.Length; j++)
                    {
                        if (mapping.Members[j].Name == member.ChoiceIdentifier.MemberName)
                        {
                            if (member.ChoiceIdentifier.Mapping.TypeDesc.UseReflection)
                                enumSource = "p[" + j.ToString() + "]";
                            else
                                enumSource = "((" + mapping.Members[j].TypeDesc.CSharpName + ")p[" + j.ToString() + "]" + ")";
                            break;
                        }
                    }
 
#if DEBUG
                    // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
                    if (enumSource == null) throw new InvalidOperationException(string.Format(ResXml.XmlInternalErrorDetails, "Can not find " + member.ChoiceIdentifier.MemberName + " in the members mapping."));
#endif
 
                }
 
                if (isRpc && member.IsReturnValue && member.Elements.Length > 0)
                {
                    Writer.Write("WriteRpcResult(");
                    WriteQuotedCSharpString(member.Elements[0].Name);
                    Writer.Write(", ");
                    WriteQuotedCSharpString("");
                    Writer.WriteLine(");");
                }
 
                // override writeAccessors choice when we've written a wrapper element
                WriteMember(source, enumSource, member.ElementsSortedByDerivation, member.Text, member.ChoiceIdentifier, member.TypeDesc, writeAccessors || hasWrapperElement);
 
                if (specifiedSource != null)
                {
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
 
                Writer.Indent--;
                Writer.WriteLine("}");
            }
 
            if (hasWrapperElement)
            {
                WriteEndElement();
            }
            if (element.IsSoap)
            {
                if (!hasWrapperElement && !writeAccessors)
                {
                    // doc/bare case -- allow extra members
                    Writer.Write("if (pLength > ");
                    Writer.Write(mapping.Members.Length.ToString());
                    Writer.WriteLine(") {");
                    Writer.Indent++;
 
                    WriteExtraMembers(mapping.Members.Length.ToString(), "pLength");
 
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
                Writer.WriteLine("WriteReferencedElements();");
            }
            Writer.Indent--;
            Writer.WriteLine("}");
            return methodName;
        }
 
        private string GenerateTypeElement(XmlTypeMapping xmlTypeMapping)
        {
            ElementAccessor element = xmlTypeMapping.Accessor;
            TypeMapping mapping = element.Mapping;
            string methodName = NextMethodName(element.Name);
            Writer.WriteLine();
            Writer.Write("public void ");
            Writer.Write(methodName);
            Writer.WriteLine("(object o) {");
            Writer.Indent++;
 
            Writer.WriteLine("WriteStartDocument();");
 
            Writer.WriteLine("if (o == null) {");
            Writer.Indent++;
            if (element.IsNullable)
            {
                if (mapping.IsSoap)
                    WriteEncodedNullTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
                else
                    WriteLiteralNullTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
            }
            else
                WriteEmptyTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""));
            Writer.WriteLine("return;");
            Writer.Indent--;
            Writer.WriteLine("}");
 
            if (!mapping.IsSoap && !mapping.TypeDesc.IsValueType && !mapping.TypeDesc.Type.GetTypeInfo().IsPrimitive)
            {
                Writer.WriteLine("TopLevelElement();");
            }
 
            WriteMember("o", null, new ElementAccessor[] { element }, null, null, mapping.TypeDesc, !element.IsSoap);
 
            if (mapping.IsSoap)
            {
                Writer.WriteLine("WriteReferencedElements();");
            }
            Writer.Indent--;
            Writer.WriteLine("}");
            return methodName;
        }
 
        private string NextMethodName(string name)
        {
            return "Write" + (++NextMethodNumber).ToString(null, NumberFormatInfo.InvariantInfo) + "_" + CodeIdentifier.MakeValidInternal(name);
        }
 
        private void WriteEnumMethod(EnumMapping mapping)
        {
            string methodName = (string)MethodNames[mapping];
            Writer.WriteLine();
            string fullTypeName = mapping.TypeDesc.CSharpName;
            if (mapping.IsSoap)
            {
                Writer.Write("void ");
                Writer.Write(methodName);
                Writer.WriteLine("(object e) {");
                WriteLocalDecl(fullTypeName, "v", "e", mapping.TypeDesc.UseReflection);
            }
            else
            {
                Writer.Write("string ");
                Writer.Write(methodName);
                Writer.Write("(");
                Writer.Write(mapping.TypeDesc.UseReflection ? "object" : fullTypeName);
                Writer.WriteLine(" v) {");
            }
            Writer.Indent++;
            Writer.WriteLine("string s = null;");
            ConstantMapping[] constants = mapping.Constants;
 
            if (constants.Length > 0)
            {
                Hashtable values = new Hashtable();
                if (mapping.TypeDesc.UseReflection)
                    Writer.WriteLine("switch (" + RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection) + " ){");
                else
                    Writer.WriteLine("switch (v) {");
                Writer.Indent++;
                for (int i = 0; i < constants.Length; i++)
                {
                    ConstantMapping c = constants[i];
                    if (values[c.Value] == null)
                    {
                        WriteEnumCase(fullTypeName, c, mapping.TypeDesc.UseReflection);
                        Writer.Write("s = ");
                        WriteQuotedCSharpString(c.XmlName);
                        Writer.WriteLine("; break;");
                        values.Add(c.Value, c.Value);
                    }
                }
 
 
                if (mapping.IsFlags)
                {
                    Writer.Write("default: s = FromEnum(");
                    Writer.Write(RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection));
                    Writer.Write(", new string[] {");
                    Writer.Indent++;
                    for (int i = 0; i < constants.Length; i++)
                    {
                        ConstantMapping c = constants[i];
                        if (i > 0)
                            Writer.WriteLine(", ");
                        WriteQuotedCSharpString(c.XmlName);
                    }
                    Writer.Write("}, new ");
                    Writer.Write(typeof(long).FullName);
                    Writer.Write("[] {");
 
                    for (int i = 0; i < constants.Length; i++)
                    {
                        ConstantMapping c = constants[i];
                        if (i > 0)
                            Writer.WriteLine(", ");
                        Writer.Write("(long)");
                        if (mapping.TypeDesc.UseReflection)
                            Writer.Write(c.Value.ToString());
                        else
                        {
                            Writer.Write(fullTypeName);
                            Writer.Write(".@");
                            CodeIdentifier.CheckValidIdentifier(c.Name);
                            Writer.Write(c.Name);
                        }
                    }
                    Writer.Indent--;
                    Writer.Write("}, ");
                    WriteQuotedCSharpString(mapping.TypeDesc.FullName);
                    Writer.WriteLine("); break;");
                }
                else
                {
                    Writer.Write("default: throw CreateInvalidEnumValueException(");
                    Writer.Write(RaCodeGen.GetStringForEnumLongValue("v", mapping.TypeDesc.UseReflection));
                    Writer.Write(".ToString(System.Globalization.CultureInfo.InvariantCulture), ");
                    WriteQuotedCSharpString(mapping.TypeDesc.FullName);
                    Writer.WriteLine(");");
                }
                Writer.Indent--;
                Writer.WriteLine("}");
            }
            if (mapping.IsSoap)
            {
                Writer.Write("WriteXsiType(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", ");
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.WriteLine(");");
                Writer.WriteLine("Writer.WriteString(s);");
            }
            else
            {
                Writer.WriteLine("return s;");
            }
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        private void WriteDerivedTypes(StructMapping mapping)
        {
            for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping)
            {
                string fullTypeName = derived.TypeDesc.CSharpName;
                Writer.Write("else if (");
                WriteTypeCompare("t", fullTypeName, derived.TypeDesc.UseReflection);
                Writer.WriteLine(") {");
                Writer.Indent++;
 
                string methodName = ReferenceMapping(derived);
 
#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("deriaved from " + mapping.TypeDesc.FullName + ", " + string.Format(ResXml.XmlInternalErrorMethod, derived.TypeDesc.Name) + Environment.StackTrace);
#endif
 
                Writer.Write(methodName);
                Writer.Write("(n, ns,");
                if (!derived.TypeDesc.UseReflection) Writer.Write("(" + fullTypeName + ")");
                Writer.Write("o");
                if (derived.TypeDesc.IsNullable)
                    Writer.Write(", isNullable");
                Writer.Write(", true");
                Writer.WriteLine(");");
                Writer.WriteLine("return;");
                Writer.Indent--;
                Writer.WriteLine("}");
 
                WriteDerivedTypes(derived);
            }
        }
 
        private void WriteEnumAndArrayTypes()
        {
            foreach (TypeScope scope in Scopes)
            {
                foreach (Mapping m in scope.TypeMappings)
                {
                    if (m is EnumMapping && !m.IsSoap)
                    {
                        EnumMapping mapping = (EnumMapping)m;
                        string fullTypeName = mapping.TypeDesc.CSharpName;
                        Writer.Write("else if (");
                        WriteTypeCompare("t", fullTypeName, mapping.TypeDesc.UseReflection);
                        Writer.WriteLine(") {");
                        Writer.Indent++;
 
                        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
                        Writer.WriteLine("Writer.WriteStartElement(n, ns);");
                        Writer.Write("WriteXsiType(");
                        WriteQuotedCSharpString(mapping.TypeName);
                        Writer.Write(", ");
                        WriteQuotedCSharpString(mapping.Namespace);
                        Writer.WriteLine(");");
                        Writer.Write("Writer.WriteString(");
                        Writer.Write(methodName);
                        Writer.Write("(");
                        if (!mapping.TypeDesc.UseReflection) Writer.Write("(" + fullTypeName + ")");
                        Writer.WriteLine("o));");
                        Writer.WriteLine("Writer.WriteEndElement();");
                        Writer.WriteLine("return;");
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                    else if (m is ArrayMapping && !m.IsSoap)
                    {
                        ArrayMapping mapping = m as ArrayMapping;
                        if (mapping == null || m.IsSoap) continue;
                        string fullTypeName = mapping.TypeDesc.CSharpName;
                        Writer.Write("else if (");
                        if (mapping.TypeDesc.IsArray)
                            WriteArrayTypeCompare("t", fullTypeName, mapping.TypeDesc.ArrayElementTypeDesc.CSharpName, mapping.TypeDesc.UseReflection);
                        else
                            WriteTypeCompare("t", fullTypeName, mapping.TypeDesc.UseReflection);
                        Writer.WriteLine(") {");
                        Writer.Indent++;
 
                        Writer.WriteLine("Writer.WriteStartElement(n, ns);");
                        Writer.Write("WriteXsiType(");
                        WriteQuotedCSharpString(mapping.TypeName);
                        Writer.Write(", ");
                        WriteQuotedCSharpString(mapping.Namespace);
                        Writer.WriteLine(");");
 
                        WriteMember("o", null, mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, true);
 
                        Writer.WriteLine("Writer.WriteEndElement();");
                        Writer.WriteLine("return;");
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                }
            }
        }
 
        private void WriteStructMethod(StructMapping mapping)
        {
            if (mapping.IsSoap && mapping.TypeDesc.IsRoot) return;
            string methodName = (string)MethodNames[mapping];
 
            Writer.WriteLine();
            Writer.Write("void ");
            Writer.Write(methodName);
 
            string fullTypeName = mapping.TypeDesc.CSharpName;
 
            if (mapping.IsSoap)
            {
                Writer.WriteLine("(object s) {");
                Writer.Indent++;
                WriteLocalDecl(fullTypeName, "o", "s", mapping.TypeDesc.UseReflection);
            }
            else
            {
                Writer.Write("(string n, string ns, ");
                Writer.Write(mapping.TypeDesc.UseReflection ? "object" : fullTypeName);
                Writer.Write(" o");
                if (mapping.TypeDesc.IsNullable)
                    Writer.Write(", bool isNullable");
                Writer.WriteLine(", bool needType) {");
                Writer.Indent++;
                if (mapping.TypeDesc.IsNullable)
                {
                    Writer.WriteLine("if ((object)o == null) {");
                    Writer.Indent++;
                    Writer.WriteLine("if (isNullable) WriteNullTagLiteral(n, ns);");
                    Writer.WriteLine("return;");
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
                Writer.WriteLine("if (!needType) {");
                Writer.Indent++;
 
                Writer.Write(typeof(Type).FullName);
                Writer.WriteLine(" t = o.GetType();");
                Writer.Write("if (");
                WriteTypeCompare("t", fullTypeName, mapping.TypeDesc.UseReflection);
                Writer.WriteLine(") {");
                Writer.WriteLine("}");
                WriteDerivedTypes(mapping);
                if (mapping.TypeDesc.IsRoot)
                    WriteEnumAndArrayTypes();
                Writer.WriteLine("else {");
 
                Writer.Indent++;
                if (mapping.TypeDesc.IsRoot)
                {
                    Writer.WriteLine("WriteTypedPrimitive(n, ns, o, true);");
                    Writer.WriteLine("return;");
                }
                else
                {
                    Writer.WriteLine("throw CreateUnknownTypeException(o);");
                }
                Writer.Indent--;
                Writer.WriteLine("}");
                Writer.Indent--;
                Writer.WriteLine("}");
            }
 
            if (!mapping.TypeDesc.IsAbstract)
            {
                if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type))
                {
                    Writer.WriteLine("EscapeName = false;");
                }
 
                string xmlnsSource = null;
                MemberMapping[] members = TypeScope.GetAllMembers(mapping);
                int xmlnsMember = FindXmlnsIndex(members);
                if (xmlnsMember >= 0)
                {
                    MemberMapping member = members[xmlnsMember];
                    CodeIdentifier.CheckValidIdentifier(member.Name);
                    xmlnsSource = RaCodeGen.GetStringForMember("o", member.Name, mapping.TypeDesc);
                    if (mapping.TypeDesc.UseReflection)
                    {
                        xmlnsSource = "((" + member.TypeDesc.CSharpName + ")" + xmlnsSource + ")";
                    }
                }
 
                if (!mapping.IsSoap)
                {
                    Writer.Write("WriteStartElement(n, ns, o, false, ");
                    if (xmlnsSource == null)
                        Writer.Write("null");
                    else
                        Writer.Write(xmlnsSource);
 
                    Writer.WriteLine(");");
                    if (!mapping.TypeDesc.IsRoot)
                    {
                        Writer.Write("if (needType) WriteXsiType(");
                        WriteQuotedCSharpString(mapping.TypeName);
                        Writer.Write(", ");
                        WriteQuotedCSharpString(mapping.Namespace);
                        Writer.WriteLine(");");
                    }
                }
                else if (xmlnsSource != null)
                {
                    WriteNamespaces(xmlnsSource);
                }
                for (int i = 0; i < members.Length; i++)
                {
                    MemberMapping m = members[i];
                    if (m.Attribute != null)
                    {
                        CodeIdentifier.CheckValidIdentifier(m.Name);
                        if (m.CheckShouldPersist)
                        {
                            Writer.Write("if (");
                            string methodInvoke = RaCodeGen.GetStringForMethodInvoke("o", fullTypeName, "ShouldSerialize" + m.Name, mapping.TypeDesc.UseReflection);
                            if (mapping.TypeDesc.UseReflection) methodInvoke = "((" + typeof(bool).FullName + ")" + methodInvoke + ")";
                            Writer.Write(methodInvoke);
                            Writer.WriteLine(") {");
                            Writer.Indent++;
                        }
                        if (m.CheckSpecified != SpecifiedAccessor.None)
                        {
                            Writer.Write("if (");
                            string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc);
                            if (mapping.TypeDesc.UseReflection) memberGet = "((" + typeof(bool).FullName + ")" + memberGet + ")";
                            Writer.Write(memberGet);
                            Writer.WriteLine(") {");
                            Writer.Indent++;
                        }
                        WriteMember(RaCodeGen.GetStringForMember("o", m.Name, mapping.TypeDesc), m.Attribute, m.TypeDesc, "o");
 
                        if (m.CheckSpecified != SpecifiedAccessor.None)
                        {
                            Writer.Indent--;
                            Writer.WriteLine("}");
                        }
                        if (m.CheckShouldPersist)
                        {
                            Writer.Indent--;
                            Writer.WriteLine("}");
                        }
                    }
                }
 
                for (int i = 0; i < members.Length; i++)
                {
                    MemberMapping m = members[i];
                    if (m.Xmlns != null)
                        continue;
                    CodeIdentifier.CheckValidIdentifier(m.Name);
                    bool checkShouldPersist = m.CheckShouldPersist && (m.Elements.Length > 0 || m.Text != null);
 
                    if (checkShouldPersist)
                    {
                        Writer.Write("if (");
                        string methodInvoke = RaCodeGen.GetStringForMethodInvoke("o", fullTypeName, "ShouldSerialize" + m.Name, mapping.TypeDesc.UseReflection);
                        if (mapping.TypeDesc.UseReflection) methodInvoke = "((" + typeof(bool).FullName + ")" + methodInvoke + ")";
                        Writer.Write(methodInvoke);
                        Writer.WriteLine(") {");
                        Writer.Indent++;
                    }
                    if (m.CheckSpecified != SpecifiedAccessor.None)
                    {
                        Writer.Write("if (");
                        string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc);
                        if (mapping.TypeDesc.UseReflection) memberGet = "((" + typeof(bool).FullName + ")" + memberGet + ")";
                        Writer.Write(memberGet);
                        Writer.WriteLine(") {");
                        Writer.Indent++;
                    }
 
                    string choiceSource = null;
                    if (m.ChoiceIdentifier != null)
                    {
                        CodeIdentifier.CheckValidIdentifier(m.ChoiceIdentifier.MemberName);
                        choiceSource = RaCodeGen.GetStringForMember("o", m.ChoiceIdentifier.MemberName, mapping.TypeDesc);
                    }
                    WriteMember(RaCodeGen.GetStringForMember("o", m.Name, mapping.TypeDesc), choiceSource, m.ElementsSortedByDerivation, m.Text, m.ChoiceIdentifier, m.TypeDesc, true);
 
                    if (m.CheckSpecified != SpecifiedAccessor.None)
                    {
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                    if (checkShouldPersist)
                    {
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                }
                if (!mapping.IsSoap)
                {
                    WriteEndElement("o");
                }
            }
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        private bool CanOptimizeWriteListSequence(TypeDesc listElementTypeDesc)
        {
            // check to see if we can write values of the attribute sequentially
            // currently we have only one data type (XmlQualifiedName) that we can not write "inline", 
            // because we need to output xmlns:qx="..." for each of the qnames
 
            return (listElementTypeDesc != null && listElementTypeDesc != QnameTypeDesc);
        }
 
        private void WriteMember(string source, AttributeAccessor attribute, TypeDesc memberTypeDesc, string parent)
        {
            if (memberTypeDesc.IsAbstract) return;
            if (memberTypeDesc.IsArrayLike)
            {
                Writer.WriteLine("{");
                Writer.Indent++;
                string fullTypeName = memberTypeDesc.CSharpName;
                WriteArrayLocalDecl(fullTypeName, "a", source, memberTypeDesc);
                if (memberTypeDesc.IsNullable)
                {
                    Writer.WriteLine("if (a != null) {");
                    Writer.Indent++;
                }
                if (attribute.IsList)
                {
                    if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc))
                    {
                        Writer.Write("Writer.WriteStartAttribute(null, ");
                        WriteQuotedCSharpString(attribute.Name);
                        Writer.Write(", ");
                        string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
                        if (ns != null)
                        {
                            WriteQuotedCSharpString(ns);
                        }
                        else
                        {
                            Writer.Write("null");
                        }
                        Writer.WriteLine(");");
                    }
                    else
                    {
                        Writer.Write(typeof(StringBuilder).FullName);
                        Writer.Write(" sb = new ");
                        Writer.Write(typeof(StringBuilder).FullName);
                        Writer.WriteLine("();");
                    }
                }
                TypeDesc arrayElementTypeDesc = memberTypeDesc.ArrayElementTypeDesc;
 
                if (memberTypeDesc.IsEnumerable)
                {
                    Writer.Write(" e = ");
                    Writer.Write(typeof(IEnumerator).FullName);
                    if (memberTypeDesc.IsPrivateImplementation)
                    {
                        Writer.Write("((");
                        Writer.Write(typeof(IEnumerable).FullName);
                        Writer.WriteLine(").GetEnumerator();");
                    }
                    else if (memberTypeDesc.IsGenericInterface)
                    {
                        if (memberTypeDesc.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(memberTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*"));
                            Writer.WriteLine(".Invoke(a, new object[0]);");
                        }
                        else
                        {
                            Writer.Write("((System.Collections.Generic.IEnumerable<");
                            Writer.Write(arrayElementTypeDesc.CSharpName);
                            Writer.WriteLine(">)a).GetEnumerator();");
                        }
                    }
                    else
                    {
                        if (memberTypeDesc.UseReflection)
                        {
                            Writer.Write("(");
                            Writer.Write(typeof(IEnumerator).FullName);
                            Writer.Write(")");
                        }
                        Writer.Write(RaCodeGen.GetStringForMethodInvoke("a", memberTypeDesc.CSharpName, "GetEnumerator", memberTypeDesc.UseReflection));
                        Writer.WriteLine(";");
                    }
                    Writer.WriteLine("if (e != null)");
                    Writer.WriteLine("while (e.MoveNext()) {");
                    Writer.Indent++;
 
                    string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
                    WriteLocalDecl(arrayTypeFullName, "ai", "e.Current", arrayElementTypeDesc.UseReflection);
                }
                else
                {
                    Writer.Write("for (int i = 0; i < ");
                    if (memberTypeDesc.IsArray)
                    {
                        Writer.WriteLine("a.Length; i++) {");
                    }
                    else
                    {
                        Writer.Write("((");
                        Writer.Write(typeof(ICollection).FullName);
                        Writer.WriteLine(")a).Count; i++) {");
                    }
                    Writer.Indent++;
                    string arrayTypeFullName = arrayElementTypeDesc.CSharpName;
                    WriteLocalDecl(arrayTypeFullName, "ai", RaCodeGen.GetStringForArrayMember("a", "i", memberTypeDesc), arrayElementTypeDesc.UseReflection);
                }
                if (attribute.IsList)
                {
                    // check to see if we can write values of the attribute sequentially
                    if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc))
                    {
                        Writer.WriteLine("if (i != 0) Writer.WriteString(\" \");");
                        Writer.Write("WriteValue(");
                    }
                    else
                    {
                        Writer.WriteLine("if (i != 0) sb.Append(\" \");");
                        Writer.Write("sb.Append(");
                    }
                    if (attribute.Mapping is EnumMapping)
                        WriteEnumValue((EnumMapping)attribute.Mapping, "ai");
                    else
                        WritePrimitiveValue(arrayElementTypeDesc, "ai", true);
                    Writer.WriteLine(");");
                }
                else
                {
                    WriteAttribute("ai", attribute, parent);
                }
                Writer.Indent--;
                Writer.WriteLine("}");
                if (attribute.IsList)
                {
                    // check to see if we can write values of the attribute sequentially
                    if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc))
                    {
                        Writer.WriteLine("Writer.WriteEndAttribute();");
                    }
                    else
                    {
                        Writer.WriteLine("if (sb.Length != 0) {");
                        Writer.Indent++;
 
                        Writer.Write("WriteAttribute(");
                        WriteQuotedCSharpString(attribute.Name);
                        Writer.Write(", ");
                        string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty;
                        if (ns != null)
                        {
                            WriteQuotedCSharpString(ns);
                            Writer.Write(", ");
                        }
                        Writer.WriteLine("sb.ToString());");
                        Writer.Indent--;
                        Writer.WriteLine("}");
                    }
                }
 
                if (memberTypeDesc.IsNullable)
                {
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
                Writer.Indent--;
                Writer.WriteLine("}");
            }
            else
            {
                WriteAttribute(source, attribute, parent);
            }
        }
 
        private void WriteAttribute(string source, AttributeAccessor attribute, string parent)
        {
            if (attribute.Mapping is SpecialMapping)
            {
                SpecialMapping special = (SpecialMapping)attribute.Mapping;
                if (special.TypeDesc.Kind == TypeKind.Attribute || special.TypeDesc.CanBeAttributeValue)
                {
                    Writer.Write("WriteXmlAttribute(");
                    Writer.Write(source);
                    Writer.Write(", ");
                    Writer.Write(parent);
                    Writer.WriteLine(");");
                }
                else
                    throw new InvalidOperationException(ResXml.XmlInternalError);
            }
            else
            {
                TypeDesc typeDesc = attribute.Mapping.TypeDesc;
                if (!typeDesc.UseReflection) source = "((" + typeDesc.CSharpName + ")" + source + ")";
                WritePrimitive("WriteAttribute", attribute.Name, attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "", attribute.Default, source, attribute.Mapping, false, false, false);
            }
        }
 
        private 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);
        }
 
 
        private 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("}");
        }
 
        private 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("}");
        }
 
        private 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 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(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(ResXml.XmlInternalError);
                }
            }
        }
 
        private void WriteElement(string 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)
            {
                Writer.Write("if (");
                Writer.Write(source);
                Writer.WriteLine(" != null) {");
                Writer.Indent++;
                string fullTypeName = element.Mapping.TypeDesc.BaseTypeDesc.CSharpName;
                string castedSource = source;
                if (!element.Mapping.TypeDesc.BaseTypeDesc.UseReflection)
                    castedSource = "((" + fullTypeName + ")" + source + ")";
                ElementAccessor e = element.Clone();
                e.Mapping = ((NullableMapping)element.Mapping).BaseMapping;
                WriteElement(e.Any ? source : castedSource, e, arrayName, writeAccessor);
                Writer.Indent--;
                Writer.WriteLine("}");
                if (element.IsNullable)
                {
                    Writer.WriteLine("else {");
                    Writer.Indent++;
                    WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
            }
            else if (element.Mapping is ArrayMapping)
            {
                ArrayMapping mapping = (ArrayMapping)element.Mapping;
                if (mapping.IsSoap)
                {
                    Writer.Write("WritePotentiallyReferencingElement(");
                    WriteQuotedCSharpString(name);
                    Writer.Write(", ");
                    WriteQuotedCSharpString(ns);
                    Writer.Write(", ");
                    Writer.Write(source);
                    if (!writeAccessor)
                    {
                        Writer.Write(", ");
                        Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
                        Writer.Write(", true, ");
                    }
                    else
                    {
                        Writer.Write(", null, false, ");
                    }
                    WriteValue(element.IsNullable);
                    Writer.WriteLine(");");
                }
                else if (element.IsUnbounded)
                {
                    TypeDesc td = mapping.TypeDesc.CreateArrayTypeDesc();
                    string fullTypeName = td.CSharpName;
                    string elementArrayName = "el" + arrayName;
                    string arrayIndex = "c" + elementArrayName;
                    Writer.WriteLine("{");
                    Writer.Indent++;
                    WriteArrayLocalDecl(fullTypeName, elementArrayName, source, mapping.TypeDesc);
                    if (element.IsNullable)
                    {
                        WriteNullCheckBegin(elementArrayName, element);
                    }
                    else
                    {
                        if (mapping.TypeDesc.IsNullable)
                        {
                            Writer.Write("if (");
                            Writer.Write(elementArrayName);
                            Writer.Write(" != null)");
                        }
                        Writer.WriteLine("{");
                        Writer.Indent++;
                    }
 
                    Writer.Write("for (int ");
                    Writer.Write(arrayIndex);
                    Writer.Write(" = 0; ");
                    Writer.Write(arrayIndex);
                    Writer.Write(" < ");
 
                    if (td.IsArray)
                    {
                        Writer.Write(elementArrayName);
                        Writer.Write(".Length");
                    }
                    else
                    {
                        Writer.Write("((");
                        Writer.Write(typeof(ICollection).FullName);
                        Writer.Write(")");
                        Writer.Write(elementArrayName);
                        Writer.Write(").Count");
                    }
                    Writer.Write("; ");
                    Writer.Write(arrayIndex);
                    Writer.WriteLine("++) {");
                    Writer.Indent++;
 
                    element.IsUnbounded = false;
                    WriteElement(elementArrayName + "[" + arrayIndex + "]", element, arrayName, writeAccessor);
                    element.IsUnbounded = true;
 
                    Writer.Indent--;
                    Writer.WriteLine("}");
 
                    Writer.Indent--;
                    Writer.WriteLine("}");
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
                else
                {
                    string fullTypeName = mapping.TypeDesc.CSharpName;
                    Writer.WriteLine("{");
                    Writer.Indent++;
                    WriteArrayLocalDecl(fullTypeName, arrayName, source, mapping.TypeDesc);
                    if (element.IsNullable)
                    {
                        WriteNullCheckBegin(arrayName, element);
                    }
                    else
                    {
                        if (mapping.TypeDesc.IsNullable)
                        {
                            Writer.Write("if (");
                            Writer.Write(arrayName);
                            Writer.Write(" != null)");
                        }
                        Writer.WriteLine("{");
                        Writer.Indent++;
                    }
                    WriteStartElement(name, ns, false);
                    WriteArrayItems(mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, arrayName, null);
                    WriteEndElement();
                    Writer.Indent--;
                    Writer.WriteLine("}");
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
            }
            else if (element.Mapping is EnumMapping)
            {
                if (element.Mapping.IsSoap)
                {
                    string methodName = (string)MethodNames[element.Mapping];
                    Writer.Write("Writer.WriteStartElement(");
                    WriteQuotedCSharpString(name);
                    Writer.Write(", ");
                    WriteQuotedCSharpString(ns);
                    Writer.WriteLine(");");
                    Writer.Write(methodName);
                    Writer.Write("(");
                    Writer.Write(source);
                    Writer.WriteLine(");");
                    WriteEndElement();
                }
                else
                {
                    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, element.Default, source, element.IsNullable, mapping.IsSoap, mapping);
                else
                {
                    string suffixNullable = mapping.IsSoap ? "Encoded" : "Literal";
                    string suffixRaw = mapping.TypeDesc.XmlEncodingNotRequired ? "Raw" : "";
                    WritePrimitive(element.IsNullable ? ("WriteNullableString" + suffixNullable + suffixRaw) : ("WriteElementString" + suffixRaw),
                                   name, ns, element.Default, source, mapping, mapping.IsSoap, true, element.IsNullable);
                }
            }
            else if (element.Mapping is StructMapping)
            {
                StructMapping mapping = (StructMapping)element.Mapping;
 
                if (mapping.IsSoap)
                {
                    Writer.Write("WritePotentiallyReferencingElement(");
                    WriteQuotedCSharpString(name);
                    Writer.Write(", ");
                    WriteQuotedCSharpString(ns);
                    Writer.Write(", ");
                    Writer.Write(source);
                    if (!writeAccessor)
                    {
                        Writer.Write(", ");
                        Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
                        Writer.Write(", true, ");
                    }
                    else
                    {
                        Writer.Write(", null, false, ");
                    }
                    WriteValue(element.IsNullable);
                }
                else
                {
                    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
                    Writer.Write(methodName);
                    Writer.Write("(");
                    WriteQuotedCSharpString(name);
                    Writer.Write(", ");
                    if (ns == null)
                        Writer.Write("null");
                    else
                    {
                        WriteQuotedCSharpString(ns);
                    }
                    Writer.Write(", ");
                    Writer.Write(source);
                    if (mapping.TypeDesc.IsNullable)
                    {
                        Writer.Write(", ");
                        WriteValue(element.IsNullable);
                    }
                    Writer.Write(", false");
                }
                Writer.WriteLine(");");
            }
            else if (element.Mapping is SpecialMapping)
            {
                SpecialMapping mapping = (SpecialMapping)element.Mapping;
                bool useReflection = mapping.TypeDesc.UseReflection;
                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
                    Writer.Write("if ((");
                    Writer.Write(source);
                    Writer.Write(") is ");
                    Writer.Write(typeof(XmlNode).FullName);
                    Writer.Write(" || ");
                    Writer.Write(source);
                    Writer.Write(" == null");
                    Writer.WriteLine(") {");
                    Writer.Indent++;
 
                    WriteElementCall("WriteElementLiteral", typeof(XmlNode), source, name, ns, element.IsNullable, element.Any);
 
                    Writer.Indent--;
                    Writer.WriteLine("}");
                    Writer.WriteLine("else {");
                    Writer.Indent++;
 
                    Writer.Write("throw CreateInvalidAnyTypeException(");
                    Writer.Write(source);
                    Writer.WriteLine(");");
 
                    Writer.Indent--;
                    Writer.WriteLine("}");
                }
            }
            else
            {
                throw new InvalidOperationException(ResXml.XmlInternalError);
            }
        }
 
        private void WriteElementCall(string func, Type cast, string source, string name, string ns, bool isNullable, bool isAny)
        {
            Writer.Write(func);
            Writer.Write("((");
            Writer.Write(cast.FullName);
            Writer.Write(")");
            Writer.Write(source);
            Writer.Write(", ");
            WriteQuotedCSharpString(name);
            Writer.Write(", ");
            WriteQuotedCSharpString(ns);
            Writer.Write(", ");
            WriteValue(isNullable);
            Writer.Write(", ");
            WriteValue(isAny);
            Writer.WriteLine(");");
        }
 
        private void WriteCheckDefault(string source, object value, bool isNullable)
        {
            Writer.Write("if (");
 
            if (value is string && ((string)value).Length == 0)
            {
                // special case for string compare
                Writer.Write("(");
                Writer.Write(source);
                if (isNullable)
                    Writer.Write(" == null) || (");
                else
                    Writer.Write(" != null) && (");
                Writer.Write(source);
                Writer.Write(".Length != 0)");
            }
            else
            {
                Writer.Write(source);
                Writer.Write(" != ");
                WriteValue(value);
            }
            Writer.Write(")");
        }
 
        private void WriteChoiceTypeCheck(string source, string fullTypeName, bool useReflection, ChoiceIdentifierAccessor choice, string enumName, TypeDesc typeDesc)
        {
            Writer.Write("if (((object)");
            Writer.Write(source);
            Writer.Write(") != null && !(");
            WriteInstanceOf(source, fullTypeName, useReflection);
            Writer.Write(")) throw CreateMismatchChoiceException(");
            WriteQuotedCSharpString(typeDesc.FullName);
            Writer.Write(", ");
            WriteQuotedCSharpString(choice.MemberName);
            Writer.Write(", ");
            WriteQuotedCSharpString(enumName);
            Writer.WriteLine(");");
        }
 
        private void WriteNullCheckBegin(string source, ElementAccessor element)
        {
            Writer.Write("if ((object)(");
            Writer.Write(source);
            Writer.WriteLine(") == null) {");
            Writer.Indent++;
            WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
            Writer.Indent--;
            Writer.WriteLine("}");
            Writer.WriteLine("else {");
            Writer.Indent++;
        }
 
        private void WriteValue(object value)
        {
            if (value == null)
            {
                Writer.Write("null");
            }
            else
            {
                Type type = value.GetType();
 
                switch (Type.GetTypeCode(type))
                {
                    case TypeCode.String:
                        {
                            string s = (string)value;
                            WriteQuotedCSharpString(s);
                        }
                        break;
                    case TypeCode.Char:
                        {
                            Writer.Write('\'');
                            char ch = (char)value;
                            if (ch == '\'')
                                Writer.Write("\'");
                            else
                                Writer.Write(ch);
                            Writer.Write('\'');
                        }
                        break;
                    case TypeCode.Int32:
                        Writer.Write(((Int32)value).ToString(null, NumberFormatInfo.InvariantInfo));
                        break;
                    case TypeCode.Double:
                        Writer.Write(((Double)value).ToString("R", NumberFormatInfo.InvariantInfo));
                        break;
                    case TypeCode.Boolean:
                        Writer.Write((bool)value ? "true" : "false");
                        break;
                    case TypeCode.Int16:
                    case TypeCode.Int64:
                    case TypeCode.UInt16:
                    case TypeCode.UInt32:
                    case TypeCode.UInt64:
                    case TypeCode.Byte:
                    case TypeCode.SByte:
                        Writer.Write("(");
                        Writer.Write(type.FullName);
                        Writer.Write(")");
                        Writer.Write("(");
                        Writer.Write(Convert.ToString(value, NumberFormatInfo.InvariantInfo));
                        Writer.Write(")");
                        break;
                    case TypeCode.Single:
                        Writer.Write(((Single)value).ToString("R", NumberFormatInfo.InvariantInfo));
                        Writer.Write("f");
                        break;
                    case TypeCode.Decimal:
                        Writer.Write(((Decimal)value).ToString(null, NumberFormatInfo.InvariantInfo));
                        Writer.Write("m");
                        break;
                    case TypeCode.DateTime:
                        Writer.Write(" new ");
                        Writer.Write(type.FullName);
                        Writer.Write("(");
                        Writer.Write(((DateTime)value).Ticks.ToString());
                        Writer.Write(")");
                        break;
                    default:
                        if (type.GetTypeInfo().IsEnum)
                        {
                            Writer.Write(((int)value).ToString(null, NumberFormatInfo.InvariantInfo));
                        }
                        else
                        {
                            throw new InvalidOperationException(string.Format(ResXml.XmlUnsupportedDefaultType, type.FullName));
                        }
                        break;
                }
            }
        }
 
        private void WriteNamespaces(string source)
        {
            Writer.Write("WriteNamespaceDeclarations(");
            Writer.Write(source);
            Writer.WriteLine(");");
        }
 
        private int FindXmlnsIndex(MemberMapping[] members)
        {
            for (int i = 0; i < members.Length; i++)
            {
                if (members[i].Xmlns == null)
                    continue;
                return i;
            }
            return -1;
        }
 
        private void WriteExtraMembers(string loopStartSource, string loopEndSource)
        {
            Writer.Write("for (int i = ");
            Writer.Write(loopStartSource);
            Writer.Write("; i < ");
            Writer.Write(loopEndSource);
            Writer.WriteLine("; i++) {");
            Writer.Indent++;
            Writer.WriteLine("if (p[i] != null) {");
            Writer.Indent++;
            Writer.WriteLine("WritePotentiallyReferencingElement(null, null, p[i], p[i].GetType(), true, false);");
            Writer.Indent--;
            Writer.WriteLine("}");
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        private void WriteLocalDecl(string typeName, string variableName, string initValue, bool useReflection)
        {
            RaCodeGen.WriteLocalDecl(typeName, variableName, initValue, useReflection);
        }
 
        private void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc)
        {
            RaCodeGen.WriteArrayLocalDecl(typeName, variableName, initValue, arrayTypeDesc);
        }
        private void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection)
        {
            RaCodeGen.WriteTypeCompare(variable, escapedTypeName, useReflection);
        }
        private void WriteInstanceOf(string source, string escapedTypeName, bool useReflection)
        {
            RaCodeGen.WriteInstanceOf(source, escapedTypeName, useReflection);
        }
        private void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection)
        {
            RaCodeGen.WriteArrayTypeCompare(variable, escapedTypeName, elementTypeName, useReflection);
        }
 
        private void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection)
        {
            RaCodeGen.WriteEnumCase(fullTypeName, c, useReflection);
        }
 
        private string FindChoiceEnumValue(ElementAccessor element, EnumMapping choiceMapping, bool useReflection)
        {
            string enumValue = null;
 
            for (int i = 0; i < choiceMapping.Constants.Length; i++)
            {
                string xmlName = choiceMapping.Constants[i].XmlName;
 
                if (element.Any && element.Name.Length == 0)
                {
                    if (xmlName == "##any:")
                    {
                        if (useReflection)
                            enumValue = choiceMapping.Constants[i].Value.ToString();
                        else
                            enumValue = choiceMapping.Constants[i].Name;
                        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)
                    {
                        if (useReflection)
                            enumValue = choiceMapping.Constants[i].Value.ToString();
                        else
                            enumValue = choiceMapping.Constants[i].Name;
                        break;
                    }
                }
            }
            if (enumValue == null || enumValue.Length == 0)
            {
                if (element.Any && element.Name.Length == 0)
                {
                    // Type {0} is missing enumeration value '##any' for XmlAnyElementAttribute.
                    throw new InvalidOperationException(string.Format(ResXml.XmlChoiceMissingAnyValue, choiceMapping.TypeDesc.FullName));
                }
                // Type {0} is missing value for '{1}'.
                throw new InvalidOperationException(string.Format(ResXml.XmlChoiceMissingValue, choiceMapping.TypeDesc.FullName, element.Namespace + ":" + element.Name, element.Name, element.Namespace));
            }
            if (!useReflection)
                CodeIdentifier.CheckValidIdentifier(enumValue);
            return enumValue;
        }
    }
 
    internal static class DynamicAssemblies
    {
        private static ArrayList s_assembliesInConfig = new ArrayList();
        private static volatile Hashtable s_nameToAssemblyMap = new Hashtable();
        private static volatile Hashtable s_assemblyToNameMap = new Hashtable();
        private static Hashtable s_tableIsTypeDynamic = Hashtable.Synchronized(new Hashtable());
 
        internal static bool IsTypeDynamic(Type type)
        {
            object oIsTypeDynamic = s_tableIsTypeDynamic[type];
            if (oIsTypeDynamic == null)
            {
                TypeInfo info = type.GetTypeInfo();
                Assembly assembly = info.Assembly;
                bool isTypeDynamic = assembly.IsDynamic;
                if (!isTypeDynamic)
                {
                    if (type.IsArray)
                    {
                        isTypeDynamic = IsTypeDynamic(type.GetElementType());
                    }
                    else if (info.IsGenericType)
                    {
                        Type[] parameterTypes = type.GetGenericArguments();
                        if (parameterTypes != null)
                        {
                            for (int i = 0; i < parameterTypes.Length; i++)
                            {
                                Type parameterType = parameterTypes[i];
                                if (!(parameterType == null || parameterType.IsGenericParameter))
                                {
                                    isTypeDynamic = IsTypeDynamic(parameterType);
                                    if (isTypeDynamic)
                                        break;
                                }
                            }
                        }
                    }
                }
                s_tableIsTypeDynamic[type] = oIsTypeDynamic = isTypeDynamic;
            }
            return (bool)oIsTypeDynamic;
        }
 
 
        internal static bool IsTypeDynamic(Type[] arguments)
        {
            foreach (Type t in arguments)
            {
                if (DynamicAssemblies.IsTypeDynamic(t))
                {
                    return true;
                }
            }
            return false;
        }
 
        internal static void Add(Assembly a)
        {
            lock (s_nameToAssemblyMap)
            {
                if (s_assemblyToNameMap[a] != null)
                {
                    //already added
                    return;
                }
                Assembly oldAssembly = s_nameToAssemblyMap[a.FullName] as Assembly;
                string key = null;
                if (oldAssembly == null)
                {
                    key = a.FullName;
                }
                else if (oldAssembly != a)
                {
                    //more than one assembly with same name
                    key = a.FullName + ", " + s_nameToAssemblyMap.Count;
                }
                if (key != null)
                {
                    s_nameToAssemblyMap.Add(key, a);
                    s_assemblyToNameMap.Add(a, key);
                }
            }
        }
        internal static Assembly Get(string fullName)
        {
            return s_nameToAssemblyMap != null ? (Assembly)s_nameToAssemblyMap[fullName] : null;
        }
        internal static string GetName(Assembly a)
        {
            return s_assemblyToNameMap != null ? (string)s_assemblyToNameMap[a] : null;
        }
    }
    internal class ReflectionAwareCodeGen
    {
        private const string hexDigits = "0123456789ABCDEF";
        private const string arrayMemberKey = "0";
        // reflectionVariables holds mapping between a reflection entity
        // referenced in the generated code (such as TypeInfo,
        // FieldInfo) and the variable which represent the entity (and
        // initialized before).
        // The types of reflection entity and corresponding key is
        // given below.
        // ----------------------------------------------------------------------------------
        // Entity           Key
        // ----------------------------------------------------------------------------------
        // Assembly         assembly.FullName
        // Type             CodeIdentifier.EscapedKeywords(type.FullName)
        // Field            fieldName+":"+CodeIdentifier.EscapedKeywords(containingType.FullName>)
        // Property         propertyName+":"+CodeIdentifier.EscapedKeywords(containingType.FullName)
        // ArrayAccessor    "0:"+CodeIdentifier.EscapedKeywords(typeof(Array).FullName)
        // MyCollectionAccessor     "0:"+CodeIdentifier.EscapedKeywords(typeof(MyCollection).FullName)
        // ----------------------------------------------------------------------------------
        private Hashtable _reflectionVariables = null;
        private int _nextReflectionVariableNumber = 0;
        private IndentedWriter _writer;
        internal ReflectionAwareCodeGen(IndentedWriter writer)
        {
            _writer = writer;
        }
 
        internal void WriteReflectionInit(TypeScope scope)
        {
            foreach (Type type in scope.Types)
            {
                TypeDesc typeDesc = scope.GetTypeDesc(type);
                if (typeDesc.UseReflection)
                    WriteTypeInfo(scope, typeDesc, type);
            }
        }
 
        private string WriteTypeInfo(TypeScope scope, TypeDesc typeDesc, Type type)
        {
            InitTheFirstTime();
            string typeFullName = typeDesc.CSharpName;
            string typeVariable = (string)_reflectionVariables[typeFullName];
            if (typeVariable != null)
                return typeVariable;
 
            if (type.IsArray)
            {
                typeVariable = GenerateVariableName("array", typeDesc.CSharpName);
                TypeDesc elementTypeDesc = typeDesc.ArrayElementTypeDesc;
                if (elementTypeDesc.UseReflection)
                {
                    string elementTypeVariable = WriteTypeInfo(scope, elementTypeDesc, scope.GetTypeFromTypeDesc(elementTypeDesc));
                    _writer.WriteLine("static " + typeof(Type).FullName + " " + typeVariable + " = " + elementTypeVariable + ".MakeArrayType();");
                }
                else
                {
                    string assemblyVariable = WriteAssemblyInfo(type);
                    _writer.Write("static " + typeof(Type).FullName + " " + typeVariable + " = " + assemblyVariable + ".GetType(");
                    WriteQuotedCSharpString(type.FullName);
                    _writer.WriteLine(");");
                }
            }
            else
            {
                typeVariable = GenerateVariableName("type", typeDesc.CSharpName);
 
                Type parameterType = Nullable.GetUnderlyingType(type);
                if (parameterType != null)
                {
                    string parameterTypeVariable = WriteTypeInfo(scope, scope.GetTypeDesc(parameterType), parameterType);
                    _writer.WriteLine("static " + typeof(Type).FullName + " " + typeVariable + " = typeof(System.Nullable<>).MakeGenericType(new " + typeof(Type).FullName + "[] {" + parameterTypeVariable + "});");
                }
                else
                {
                    string assemblyVariable = WriteAssemblyInfo(type);
                    _writer.Write("static " + typeof(Type).FullName + " " + typeVariable + " = " + assemblyVariable + ".GetType(");
                    WriteQuotedCSharpString(type.FullName);
                    _writer.WriteLine(");");
                }
            }
 
            _reflectionVariables.Add(typeFullName, typeVariable);
 
            TypeMapping mapping = scope.GetTypeMappingFromTypeDesc(typeDesc);
            if (mapping != null)
                WriteMappingInfo(mapping, typeVariable, type);
            if (typeDesc.IsCollection || typeDesc.IsEnumerable)
            {// Arrays use the generic item_Array
                TypeDesc elementTypeDesc = typeDesc.ArrayElementTypeDesc;
                if (elementTypeDesc.UseReflection)
                    WriteTypeInfo(scope, elementTypeDesc, scope.GetTypeFromTypeDesc(elementTypeDesc));
                WriteCollectionInfo(typeVariable, typeDesc, type);
            }
            return typeVariable;
        }
 
        private void InitTheFirstTime()
        {
            if (_reflectionVariables == null)
            {
                _reflectionVariables = new Hashtable();
                _writer.Write(String.Format(CultureInfo.InvariantCulture, s_helperClassesForUseReflection,
                    "object", "string", typeof(Type).FullName,
                    typeof(FieldInfo).FullName, typeof(PropertyInfo).FullName,
                    typeof(MemberInfo).FullName, string.Empty /*typeof(MemberTypes).FullName*/));
 
                WriteDefaultIndexerInit(typeof(IList), typeof(Array).FullName, false, false);
            }
        }
 
        private void WriteMappingInfo(TypeMapping mapping, string typeVariable, Type type)
        {
            string typeFullName = mapping.TypeDesc.CSharpName;
            if (mapping is StructMapping)
            {
                StructMapping structMapping = mapping as StructMapping;
                for (int i = 0; i < structMapping.Members.Length; i++)
                {
                    MemberMapping member = structMapping.Members[i];
                    string memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, member.Name);
                    if (member.CheckShouldPersist)
                    {
                        string memberName = "ShouldSerialize" + member.Name;
                        memberVariable = WriteMethodInfo(typeFullName, typeVariable, memberName, false);
                    }
                    if (member.CheckSpecified != SpecifiedAccessor.None)
                    {
                        string memberName = member.Name + "Specified";
                        memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, memberName);
                    }
                    if (member.ChoiceIdentifier != null)
                    {
                        string memberName = member.ChoiceIdentifier.MemberName;
                        memberVariable = WriteMemberInfo(type, typeFullName, typeVariable, memberName);
                    }
                }
            }
            else if (mapping is EnumMapping)
            {
                FieldInfo[] enumFields = type.GetFields();
                for (int i = 0; i < enumFields.Length; i++)
                {
                    WriteMemberInfo(type, typeFullName, typeVariable, enumFields[i].Name);
                }
            }
        }
        private void WriteCollectionInfo(string typeVariable, TypeDesc typeDesc, Type type)
        {
            string typeFullName = CodeIdentifier.GetCSharpName(type);
            string elementTypeFullName = typeDesc.ArrayElementTypeDesc.CSharpName;
            bool elementUseReflection = typeDesc.ArrayElementTypeDesc.UseReflection;
            if (typeDesc.IsCollection)
            {
                WriteDefaultIndexerInit(type, typeFullName, typeDesc.UseReflection, elementUseReflection);
            }
            else if (typeDesc.IsEnumerable)
            {
                if (typeDesc.IsGenericInterface)
                {
                    WriteMethodInfo(typeFullName, typeVariable, "System.Collections.Generic.IEnumerable*", true);
                }
                else if (!typeDesc.IsPrivateImplementation)
                {
                    WriteMethodInfo(typeFullName, typeVariable, "GetEnumerator", true);
                }
            }
            WriteMethodInfo(typeFullName, typeVariable, "Add", false, GetStringForTypeof(elementTypeFullName, elementUseReflection));
        }
 
        private string WriteAssemblyInfo(Type type)
        {
            TypeInfo info = type.GetTypeInfo();
            string assemblyFullName = info.Assembly.FullName;
            string assemblyVariable = (string)_reflectionVariables[assemblyFullName];
            if (assemblyVariable == null)
            {
                int iComma = assemblyFullName.IndexOf(',');
                string assemblyName = (iComma > -1) ? assemblyFullName.Substring(0, iComma) : assemblyFullName;
                assemblyVariable = GenerateVariableName("assembly", assemblyName);
                //writer.WriteLine("static "+ typeof(Assembly).FullName+" "+assemblyVariable+" = "+typeof(Assembly).FullName+".Load(");
                _writer.Write("static " + typeof(Assembly).FullName + " " + assemblyVariable + " = " + "ResolveDynamicAssembly(");
                WriteQuotedCSharpString(DynamicAssemblies.GetName(info.Assembly)/*assemblyFullName*/);
                _writer.WriteLine(");");
                _reflectionVariables.Add(assemblyFullName, assemblyVariable);
            }
            return assemblyVariable;
        }
 
        private string WriteMemberInfo(Type type, string escapedName, string typeVariable, string memberName)
        {
            MemberInfo[] memberInfos = type.GetMember(memberName);
            for (int i = 0; i < memberInfos.Length; i++)
            {
                MemberInfo memberInfo = memberInfos[i];
                if (memberInfo is PropertyInfo)
                {
                    string propVariable = GenerateVariableName("prop", memberName);
                    _writer.Write("static XSPropInfo " + propVariable + " = new XSPropInfo(" + typeVariable + ", ");
                    WriteQuotedCSharpString(memberName);
                    _writer.WriteLine(");");
                    _reflectionVariables.Add(memberName + ":" + escapedName, propVariable);
                    return propVariable;
                }
                else if (memberInfo is FieldInfo)
                {
                    string fieldVariable = GenerateVariableName("field", memberName);
                    _writer.Write("static XSFieldInfo " + fieldVariable + " = new XSFieldInfo(" + typeVariable + ", ");
                    WriteQuotedCSharpString(memberName);
                    _writer.WriteLine(");");
                    _reflectionVariables.Add(memberName + ":" + escapedName, fieldVariable);
                    return fieldVariable;
                }
            }
            throw new InvalidOperationException(string.Format(ResXml.XmlSerializerUnsupportedType, memberInfos[0].ToString()));
        }
 
        private string WriteMethodInfo(string escapedName, string typeVariable, string memberName, bool isNonPublic, params string[] paramTypes)
        {
            string methodVariable = GenerateVariableName("method", memberName);
            _writer.Write("static " + typeof(MethodInfo).FullName + " " + methodVariable + " = " + typeVariable + ".GetMethod(");
            WriteQuotedCSharpString(memberName);
            _writer.Write(", ");
 
            string bindingFlags = typeof(BindingFlags).FullName;
            _writer.Write(bindingFlags);
            _writer.Write(".Public | ");
            _writer.Write(bindingFlags);
            _writer.Write(".Instance | ");
            _writer.Write(bindingFlags);
            _writer.Write(".Static");
 
            if (isNonPublic)
            {
                _writer.Write(" | ");
                _writer.Write(bindingFlags);
                _writer.Write(".NonPublic");
            }
            _writer.Write(", null, ");
            _writer.Write("new " + typeof(Type).FullName + "[] { ");
            for (int i = 0; i < paramTypes.Length; i++)
            {
                _writer.Write(paramTypes[i]);
                if (i < (paramTypes.Length - 1))
                    _writer.Write(", ");
            }
            _writer.WriteLine("}, null);");
            _reflectionVariables.Add(memberName + ":" + escapedName, methodVariable);
            return methodVariable;
        }
 
        private string WriteDefaultIndexerInit(Type type, string escapedName, bool collectionUseReflection, bool elementUseReflection)
        {
            string itemVariable = GenerateVariableName("item", escapedName);
            PropertyInfo defaultIndexer = TypeScope.GetDefaultIndexer(type, null);
            _writer.Write("static XSArrayInfo ");
            _writer.Write(itemVariable);
            _writer.Write("= new XSArrayInfo(");
            _writer.Write(GetStringForTypeof(CodeIdentifier.GetCSharpName(type), collectionUseReflection));
            _writer.Write(".GetProperty(");
            WriteQuotedCSharpString(defaultIndexer.Name);
            _writer.Write(",");
            //defaultIndexer.PropertyType is same as TypeDesc.ElementTypeDesc
            _writer.Write(GetStringForTypeof(CodeIdentifier.GetCSharpName(defaultIndexer.PropertyType), elementUseReflection));
            _writer.Write(",new ");
            _writer.Write(typeof(Type[]).FullName);
            _writer.WriteLine("{typeof(int)}));");
            _reflectionVariables.Add(arrayMemberKey + ":" + escapedName, itemVariable);
            return itemVariable;
        }
 
        private string GenerateVariableName(string prefix, string fullName)
        {
            ++_nextReflectionVariableNumber;
            return prefix + _nextReflectionVariableNumber + "_" +
                CodeIdentifier.MakeValidInternal(fullName.Replace('.', '_'));
        }
        internal string GetReflectionVariable(string typeFullName, string memberName)
        {
            string key;
            if (memberName == null)
                key = typeFullName;
            else
                key = memberName + ":" + typeFullName;
            return (string)_reflectionVariables[key];
        }
 
 
        internal string GetStringForMethodInvoke(string obj, string escapedTypeName, string methodName, bool useReflection, params string[] args)
        {
            StringBuilder sb = new StringBuilder();
            if (useReflection)
            {
                sb.Append(GetReflectionVariable(escapedTypeName, methodName));
                sb.Append(".Invoke(");
                sb.Append(obj);
                sb.Append(", new object[] {");
            }
            else
            {
                sb.Append(obj);
                sb.Append(".@");
                sb.Append(methodName);
                sb.Append("(");
            }
            for (int i = 0; i < args.Length; i++)
            {
                if (i != 0)
                    sb.Append(", ");
                sb.Append(args[i]);
            }
            if (useReflection)
                sb.Append("})");
            else
                sb.Append(")");
            return sb.ToString();
        }
 
        internal string GetStringForEnumCompare(EnumMapping mapping, string memberName, bool useReflection)
        {
            if (!useReflection)
            {
                CodeIdentifier.CheckValidIdentifier(memberName);
                return mapping.TypeDesc.CSharpName + ".@" + memberName;
            }
            string memberAccess = GetStringForEnumMember(mapping.TypeDesc.CSharpName, memberName, useReflection);
            return GetStringForEnumLongValue(memberAccess, useReflection);
        }
        internal string GetStringForEnumLongValue(string variable, bool useReflection)
        {
            if (useReflection)
                return typeof(Convert).FullName + ".ToInt64(" + variable + ")";
            return "((" + typeof(long).FullName + ")" + variable + ")";
        }
 
        internal string GetStringForTypeof(string typeFullName, bool useReflection)
        {
            if (useReflection)
            {
                return GetReflectionVariable(typeFullName, null);
            }
            else
            {
                return "typeof(" + typeFullName + ")";
            }
        }
        internal string GetStringForMember(string obj, string memberName, TypeDesc typeDesc)
        {
            if (!typeDesc.UseReflection)
                return obj + ".@" + memberName;
 
            TypeDesc saveTypeDesc = typeDesc;
            while (typeDesc != null)
            {
                string typeFullName = typeDesc.CSharpName;
                string memberInfoName = GetReflectionVariable(typeFullName, memberName);
                if (memberInfoName != null)
                    return memberInfoName + "[" + obj + "]";
                // member may be part of the basetype 
                typeDesc = typeDesc.BaseTypeDesc;
                if (typeDesc != null && !typeDesc.UseReflection)
                    return "((" + typeDesc.CSharpName + ")" + obj + ").@" + memberName;
            }
            //throw GetReflectionVariableException(saveTypeDesc.CSharpName,memberName); 
            // NOTE, sowmys:Must never happen. If it does let the code
            // gen continue to help debugging what's gone wrong.
            // Eventually the compilation will fail.
            return "[" + obj + "]";
        }
        /*
        Exception GetReflectionVariableException(string typeFullName, string memberName){
            string key;
            if(memberName == null)
                key = typeFullName;
            else
                key = memberName+":"+typeFullName;
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            foreach(object varAvail in reflectionVariables.Keys){
                sb.Append(varAvail.ToString());
                sb.Append("\n");
            }
            return new Exception("No reflection variable for " + key + "\nAvailable keys\n"+sb.ToString());
        }*/
 
        internal string GetStringForEnumMember(string typeFullName, string memberName, bool useReflection)
        {
            if (!useReflection)
                return typeFullName + ".@" + memberName;
 
            string memberInfoName = GetReflectionVariable(typeFullName, memberName);
            return memberInfoName + "[null]";
        }
        internal string GetStringForArrayMember(string arrayName, string subscript, TypeDesc arrayTypeDesc)
        {
            if (!arrayTypeDesc.UseReflection)
            {
                return arrayName + "[" + subscript + "]";
            }
            string typeFullName = arrayTypeDesc.IsCollection ? arrayTypeDesc.CSharpName : typeof(Array).FullName;
            string arrayInfo = GetReflectionVariable(typeFullName, arrayMemberKey);
            return arrayInfo + "[" + arrayName + ", " + subscript + "]";
        }
        internal string GetStringForMethod(string obj, string typeFullName, string memberName, bool useReflection)
        {
            if (!useReflection)
                return obj + "." + memberName + "(";
 
            string memberInfoName = GetReflectionVariable(typeFullName, memberName);
            return memberInfoName + ".Invoke(" + obj + ", new object[]{";
        }
        internal string GetStringForCreateInstance(string escapedTypeName, bool useReflection, bool ctorInaccessible, bool cast)
        {
            return GetStringForCreateInstance(escapedTypeName, useReflection, ctorInaccessible, cast, string.Empty);
        }
 
        internal string GetStringForCreateInstance(string escapedTypeName, bool useReflection, bool ctorInaccessible, bool cast, string arg)
        {
            if (!useReflection && !ctorInaccessible)
                return "new " + escapedTypeName + "(" + arg + ")";
            return GetStringForCreateInstance(GetStringForTypeof(escapedTypeName, useReflection), cast && !useReflection ? escapedTypeName : null, ctorInaccessible, arg);
        }
 
        internal string GetStringForCreateInstance(string type, string cast, bool nonPublic, string arg)
        {
            StringBuilder createInstance = new StringBuilder();
            if (cast != null && cast.Length > 0)
            {
                createInstance.Append("(");
                createInstance.Append(cast);
                createInstance.Append(")");
            }
            createInstance.Append(typeof(Activator).FullName);
            createInstance.Append(".CreateInstance(");
            createInstance.Append(type);
            createInstance.Append(", ");
            string bindingFlags = typeof(BindingFlags).FullName;
            createInstance.Append(bindingFlags);
            createInstance.Append(".Instance | ");
            createInstance.Append(bindingFlags);
            createInstance.Append(".Public | ");
            createInstance.Append(bindingFlags);
            createInstance.Append(".CreateInstance");
 
            if (nonPublic)
            {
                createInstance.Append(" | ");
                createInstance.Append(bindingFlags);
                createInstance.Append(".NonPublic");
            }
            if (arg == null || arg.Length == 0)
            {
                createInstance.Append(", null, new object[0], null)");
            }
            else
            {
                createInstance.Append(", null, new object[] { ");
                createInstance.Append(arg);
                createInstance.Append(" }, null)");
            }
            return createInstance.ToString();
        }
 
        internal void WriteLocalDecl(string typeFullName, string variableName, string initValue, bool useReflection)
        {
            if (useReflection)
                typeFullName = "object";
            _writer.Write(typeFullName);
            _writer.Write(" ");
            _writer.Write(variableName);
            if (initValue != null)
            {
                _writer.Write(" = ");
                if (!useReflection && initValue != "null")
                {
                    _writer.Write("(" + typeFullName + ")");
                }
                _writer.Write(initValue);
            }
            _writer.WriteLine(";");
        }
 
        internal void WriteCreateInstance(string escapedName, string source, bool useReflection, bool ctorInaccessible)
        {
            _writer.Write(useReflection ? "object" : escapedName);
            _writer.Write(" ");
            _writer.Write(source);
            _writer.Write(" = ");
            _writer.Write(GetStringForCreateInstance(escapedName, useReflection, ctorInaccessible, !useReflection && ctorInaccessible));
            _writer.WriteLine(";");
        }
        internal void WriteInstanceOf(string source, string escapedTypeName, bool useReflection)
        {
            if (!useReflection)
            {
                _writer.Write(source);
                _writer.Write(" is ");
                _writer.Write(escapedTypeName);
                return;
            }
            _writer.Write(GetReflectionVariable(escapedTypeName, null));
            _writer.Write(".IsAssignableFrom(");
            _writer.Write(source);
            _writer.Write(".GetType())");
        }
 
        internal void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc)
        {
            if (arrayTypeDesc.UseReflection)
            {
                if (arrayTypeDesc.IsEnumerable)
                    typeName = typeof(IEnumerable).FullName;
                else if (arrayTypeDesc.IsCollection)
                    typeName = typeof(ICollection).FullName;
                else
                    typeName = typeof(Array).FullName;
            }
            _writer.Write(typeName);
            _writer.Write(" ");
            _writer.Write(variableName);
            if (initValue != null)
            {
                _writer.Write(" = ");
                if (initValue != "null")
                    _writer.Write("(" + typeName + ")");
                _writer.Write(initValue);
            }
            _writer.WriteLine(";");
        }
        internal void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection)
        {
            _writer.Write("case ");
            if (useReflection)
            {
                _writer.Write(c.Value.ToString());
            }
            else
            {
                _writer.Write(fullTypeName);
                _writer.Write(".@");
                CodeIdentifier.CheckValidIdentifier(c.Name);
                _writer.Write(c.Name);
            }
            _writer.Write(": ");
        }
        internal void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection)
        {
            _writer.Write(variable);
            _writer.Write(" == ");
            _writer.Write(GetStringForTypeof(escapedTypeName, useReflection));
        }
        internal void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection)
        {
            if (!useReflection)
            {
                _writer.Write(variable);
                _writer.Write(" == typeof(");
                _writer.Write(escapedTypeName);
                _writer.Write(")");
                return;
            }
            _writer.Write(variable);
            _writer.Write(".IsArray ");
            _writer.Write(" && ");
            WriteTypeCompare(variable + ".GetElementType()", elementTypeName, useReflection);
        }
 
        internal static void WriteQuotedCSharpString(IndentedWriter writer, string value)
        {
            if (value == null)
            {
                writer.Write("null");
                return;
            }
            writer.Write("@\"");
            foreach (char ch in value)
            {
                if (ch < 32)
                {
                    if (ch == '\r')
                        writer.Write("\\r");
                    else if (ch == '\n')
                        writer.Write("\\n");
                    else if (ch == '\t')
                        writer.Write("\\t");
                    else
                    {
                        byte b = (byte)ch;
                        writer.Write("\\x");
                        writer.Write(hexDigits[b >> 4]);
                        writer.Write(hexDigits[b & 0xF]);
                    }
                }
                else if (ch == '\"')
                {
                    writer.Write("\"\"");
                }
                else
                {
                    writer.Write(ch);
                }
            }
            writer.Write("\"");
        }
 
        internal void WriteQuotedCSharpString(string value)
        {
            WriteQuotedCSharpString(_writer, value);
        }
 
        private static string s_helperClassesForUseReflection = @"
    sealed class XSFieldInfo {{
       {3} fieldInfo;
        public XSFieldInfo({2} t, {1} memberName){{
            fieldInfo = t.GetField(memberName);
        }}
        public {0} this[{0} o] {{
            get {{
                return fieldInfo.GetValue(o);
            }}
            set {{
                fieldInfo.SetValue(o, value);
            }}
        }}
 
    }}
    sealed class XSPropInfo {{
        {4} propInfo;
        public XSPropInfo({2} t, {1} memberName){{
            propInfo = t.GetProperty(memberName);
        }}
        public {0} this[{0} o] {{
            get {{
                return propInfo.GetValue(o, null);
            }}
            set {{
                propInfo.SetValue(o, value, null);
            }}
        }}
    }}
    sealed class XSArrayInfo {{
        {4} propInfo;
        public XSArrayInfo({4} propInfo){{
            this.propInfo = propInfo;
        }}
        public {0} this[{0} a, int i] {{
            get {{
                return propInfo.GetValue(a, new {0}[]{{i}});
            }}
            set {{
                propInfo.SetValue(a, value, new {0}[]{{i}});
            }}
        }}
    }}
";
    }
}