XmlSerializationWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Serialization / XmlSerializationWriter.cs / 1305376 / XmlSerializationWriter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Xml.Serialization { 

    using System; 
    using System.IO;
    using System.Collections;
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.Xml.Schema;
    using System.ComponentModel; 
    using System.Diagnostics; 
    using System.CodeDom.Compiler;
    using System.Globalization; 
    using System.Text;
    using System.Threading;
    using System.Security.Permissions;
    using System.Runtime.Versioning; 

    ///  
    /// 
    public abstract class XmlSerializationWriter : XmlSerializationGeneratedCode {
        XmlWriter w; 
        XmlSerializerNamespaces namespaces;
        int tempNamespacePrefix;
        Hashtable usedPrefixes;
        Hashtable references; 
        string idBase;
        int nextId; 
        Hashtable typeEntries; 
        ArrayList referencesToWrite;
        Hashtable objectsInUse; 
        string aliasBase = "q";
        bool soap12;
        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) { 
            this.w = w; 
            this.namespaces = namespaces;
            this.soap12 = (encodingStyle == Soap12.Encoding); 
            this.idBase = idBase;
            Init(tempAssembly);
        }
 
        /// 
        protected bool EscapeName { 
            get { 
                return escapeName;
            } 
            set {
                escapeName = value;
            }
        } 

        ///  
        protected XmlWriter Writer { 
            get {
                return w; 
            }
            set {
                w = value;
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        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);
                } 
            }
        } 
 
        /// 
        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;
        } 
 
        /// 
        /// 
        protected static Assembly ResolveDynamicAssembly(string assemblyFullName){
            return DynamicAssemblies.Get(assemblyFullName);
        }
 
        /// 
        protected static string FromByteArrayHex(byte[] value) { 
            return XmlCustomFormatter.FromByteArrayHex(value); 
        }
 
        /// 
        protected static string FromDateTime(DateTime value) {
            return XmlCustomFormatter.FromDateTime(value);
        } 

        ///  
        protected static string FromDate(DateTime value) { 
            return XmlCustomFormatter.FromDate(value);
        } 

        /// 
        protected static string FromTime(DateTime value) {
            return XmlCustomFormatter.FromTime(value); 
        }
 
        ///  
        protected static string FromChar(char value) {
            return XmlCustomFormatter.FromChar(value); 
        }

        /// 
        protected static string FromEnum(long value, string[] values, long[] ids) { 
            return XmlCustomFormatter.FromEnum(value, values, ids, null);
        } 
 
        /// 
        protected static string FromEnum(long value, string[] values, long[] ids, string typeName) { 
            return XmlCustomFormatter.FromEnum(value, values, ids, typeName);
        }

        ///  
        protected static string FromXmlName(string name) {
            return XmlCustomFormatter.FromXmlName(name); 
        } 

        ///  
        protected static string FromXmlNCName(string ncName) {
            return XmlCustomFormatter.FromXmlNCName(ncName);
        }
 
        /// 
        protected static string FromXmlNmToken(string nmToken) { 
            return XmlCustomFormatter.FromXmlNmToken(nmToken); 
        }
 
        /// 
        protected static string FromXmlNmTokens(string nmTokens) {
            return XmlCustomFormatter.FromXmlNmTokens(nmTokens);
        } 

        ///  
        protected void WriteXsiType(string name, string ns) { 
            WriteAttribute("type", XmlSchema.InstanceNamespace, GetQualifiedName(name, ns));
        } 

        XmlQualifiedName GetPrimitiveTypeName(Type type) {
            return GetPrimitiveTypeName(type, true);
        } 

        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);
        } 
 
        /// 
        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
        protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName) { 
            return FromXmlQualifiedName(xmlQualifiedName, true);
        } 
 
        /// 
        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);
        } 

        ///  
        protected void WriteStartElement(string name) { 
            WriteStartElement(name, null, null, false, null);
        } 

        /// 
        protected void WriteStartElement(string name, string ns) {
            WriteStartElement(name, ns, null, false, null); 
        }
 
        ///  
        protected void WriteStartElement(string name, string ns, bool writePrefixed) {
            WriteStartElement(name, ns, null, writePrefixed, null); 
        }

        /// 
        protected void WriteStartElement(string name, string ns, object o) { 
            WriteStartElement(name, ns, o, false, null);
        } 
 
        /// 
        protected void WriteStartElement(string name, string ns, object o, bool writePrefixed) { 
            WriteStartElement(name, ns, o, writePrefixed, null);
        }

        ///  
        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(Res.GetString(Res.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(Res.GetString(Res.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); 
        } 

        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;
        } 
 
        /// 
        protected void WriteNullTagEncoded(string name) { 
            WriteNullTagEncoded(name, null);
        }

        ///  
        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();
        }

        ///  
        protected void WriteNullTagLiteral(string name) {
            WriteNullTagLiteral(name, null); 
        } 

        ///  
        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(); 
        } 

        ///  
        protected void WriteEmptyTag(string name) {
            WriteEmptyTag(name, null);
        }
 
        /// 
        protected void WriteEmptyTag(string name, string ns) { 
            if (name == null || name.Length == 0) 
                return;
            WriteStartElement(name, ns, null, false); 
            w.WriteEndElement();
        }

        ///  
        protected void WriteEndElement() {
            w.WriteEndElement(); 
        } 

        ///  
        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(Res.GetString(Res.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName)); 
#endif
 
                objectsInUse.Remove(o);
            }
        }
 
        /// 
        protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable) { 
            WriteSerializable(serializable, name, ns, isNullable, true); 
        }
 
        /// 
        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();
            } 
        }
 
        ///  
        protected void WriteNullableStringEncoded(string name, string ns, string value, XmlQualifiedName xsiType) {
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else
                WriteElementString(name, ns, value, xsiType);
        } 

        ///  
        protected void WriteNullableStringLiteral(string name, string ns, string value) { 
            if (value == null)
                WriteNullTagLiteral(name, ns); 
            else
                WriteElementString(name, ns, value, null);
        }
 

        ///  
        protected void WriteNullableStringEncodedRaw(string name, string ns, string value, XmlQualifiedName xsiType) { 
            if (value == null)
                WriteNullTagEncoded(name, ns); 
            else
                WriteElementStringRaw(name, ns, value, xsiType);
        }
 
        /// 
        protected void WriteNullableStringEncodedRaw(string name, string ns, byte[] value, XmlQualifiedName xsiType) { 
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else 
                WriteElementStringRaw(name, ns, value, xsiType);
        }

        ///  
        protected void WriteNullableStringLiteralRaw(string name, string ns, string value) {
            if (value == null) 
                WriteNullTagLiteral(name, ns); 
            else
                WriteElementStringRaw(name, ns, value, null); 
        }

        /// 
        protected void WriteNullableStringLiteralRaw(string name, string ns, byte[] value) { 
            if (value == null)
                WriteNullTagLiteral(name, ns); 
            else 
                WriteElementStringRaw(name, ns, value, null);
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        protected void WriteNullableQualifiedNameEncoded(string name, string ns, XmlQualifiedName value, XmlQualifiedName xsiType) { 
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else 
                WriteElementQualifiedName(name, ns, value, xsiType);
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected void WriteNullableQualifiedNameLiteral(string name, string ns, XmlQualifiedName value) {
            if (value == null) 
                WriteNullTagLiteral(name, ns);
            else
                WriteElementQualifiedName(name, ns, value, null);
        } 

 
        ///  
        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); 
        }
 
        ///  
        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(Res.GetString(Res.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(Res.GetString(Res.XmlElementNameMismatch, node.LocalName, node.NamespaceURI, name, ns));
                } 
            }
            else 
                w.WriteStartElement(name, ns); 

            node.WriteTo(w); 

            if (!any)
                w.WriteEndElement();
        } 

        ///  
        protected Exception CreateUnknownTypeException(object o) { 
            return CreateUnknownTypeException(o.GetType());
        } 

        /// 
        protected Exception CreateUnknownTypeException(Type type) {
            if (typeof(IXmlSerializable).IsAssignableFrom(type)) return new InvalidOperationException(Res.GetString(Res.XmlInvalidSerializable, type.FullName)); 
            TypeDesc typeDesc = new TypeScope().GetTypeDesc(type);
            if (!typeDesc.IsStructLike) return new InvalidOperationException(Res.GetString(Res.XmlInvalidUseOfType, type.FullName)); 
            return new InvalidOperationException(Res.GetString(Res.XmlUnxpectedType, type.FullName)); 
        }
 
        /// 
        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(Res.GetString(Res.XmlChoiceMismatchChoiceException, elementName, value, enumValue)); 
        }
 
        ///  
        protected Exception CreateUnknownAnyElementException(string name, string ns) {
            return new InvalidOperationException(Res.GetString(Res.XmlUnknownAnyElement, name, ns)); 
        }

        /// 
        protected Exception CreateInvalidChoiceIdentifierValueException(string type, string identifier) { 
            return new InvalidOperationException(Res.GetString(Res.XmlInvalidChoiceIdentifierValue, type, identifier));
        } 
 
        /// 
        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(Res.GetString(Res.XmlChoiceIdentifierMismatch, value, identifier, name, ns));
        }
 
        /// 
        protected Exception CreateInvalidEnumValueException(object value, string typeName) { 
            return new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, value, typeName)); 
        }
 
        /// 
        protected Exception CreateInvalidAnyTypeException(object o) {
            return CreateInvalidAnyTypeException(o.GetType());
        } 

        ///  
        protected Exception CreateInvalidAnyTypeException(Type type) { 
            return new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, type.FullName));
        } 

        /// 
        protected void WriteReferencingElement(string n, string ns, object o) {
            WriteReferencingElement(n, ns, o, false); 
        }
 
        ///  
        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(); 
        }

        bool IsIdDefined(object o) {
            if (references != null) return references.Contains(o); 
            else return false;
        } 
 
        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(CultureInfo.InvariantCulture); 
                references.Add(o, id); 
                if (addToReferencesList) referencesToWrite.Add(o);
            } 
            return id;
        }

        ///  
        protected void WriteId(object o) {
            WriteId(o, true); 
        } 

        void WriteId(object o, bool addToReferencesList) { 
            if (soap12)
                w.WriteAttributeString("id", Soap12.Encoding, GetId(o, addToReferencesList));
            else
                w.WriteAttributeString("id", GetId(o, addToReferencesList)); 
        }
 
        ///  
        protected void WriteXmlAttribute(XmlNode node) {
            WriteXmlAttribute(node, null); 
        }

        /// 
        protected void WriteXmlAttribute(XmlNode node, object container) { 
            XmlAttribute attr = node as XmlAttribute;
            if (attr == null) throw new InvalidOperationException(Res.GetString(Res.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;
 
                    //
                    WriteAttribute(Wsdl.ArrayType, Wsdl.Namespace, value); 
                } 
                else {
                    WriteAttribute(attr.Name, attr.NamespaceURI, attr.Value); 
                }
            }
        }
 
        /// 
        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);
                } 
            }
        }

        ///  
        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();
            }
        } 

        ///  
        protected void WriteAttribute(string localName, string value) { 
            if (value == null) return;
            w.WriteAttributeString(localName, null, value); 
        }

        /// 
        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(); 
        }

        /// 
        protected void WriteAttribute(string prefix, string localName, string ns, string value) { 
            if (value == null) return;
            w.WriteAttributeString(prefix, localName, null, value); 
        } 

        ///  
        protected void WriteValue(string value) {
            if (value == null) return;
            w.WriteString(value);
        } 

        ///  
        protected void WriteValue(byte[] value) { 
            if (value == null) return;
            XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length); 
        }

        /// 
        protected void WriteStartDocument() { 
            if (w.WriteState == WriteState.Start) {
                w.WriteStartDocument(); 
            } 
        }
 
        /// 
        protected void WriteElementString(String localName, String value) {
            WriteElementString(localName, null, value, null);
        } 

        ///  
        protected void WriteElementString(String localName, String ns, String value) { 
            WriteElementString(localName, ns, value, null);
        } 

        /// 
        protected void WriteElementString(String localName, String value, XmlQualifiedName xsiType) {
            WriteElementString(localName, null, value, xsiType); 
        }
 
        ///  
        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(); 
            }
        } 

        /// 
        protected void WriteElementStringRaw(String localName, String value) {
            WriteElementStringRaw(localName,null,value, null); 
        }
 
        ///  
        protected void WriteElementStringRaw(String localName, byte[] value) {
            WriteElementStringRaw(localName,null,value, null); 
        }

        /// 
        protected void WriteElementStringRaw(String localName, String ns, String value) { 
            WriteElementStringRaw(localName, ns, value, null);
        } 
 
        /// 
        protected void WriteElementStringRaw(String localName, String ns, byte[] value) { 
            WriteElementStringRaw(localName, ns, value, null);
        }

        ///  
        protected void WriteElementStringRaw(String localName, String value, XmlQualifiedName xsiType) {
            WriteElementStringRaw(localName,null,value, xsiType); 
        } 

        ///  
        protected void WriteElementStringRaw(String localName, byte[] value, XmlQualifiedName xsiType) {
            WriteElementStringRaw(localName, null, value, xsiType);
        }
 
        /// 
        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();
        } 

        ///  
        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(); 
        }
 
        ///  
        protected void WriteRpcResult(string name, string ns) {
            if (!soap12) return; 
            WriteElementQualifiedName(Soap12.RpcResult, Soap12.RpcNamespace, new XmlQualifiedName(name, ns), null);
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected void WriteElementQualifiedName(String localName, XmlQualifiedName value) {
            WriteElementQualifiedName(localName,null,value, null); 
        }

        /// 
        protected void WriteElementQualifiedName(string localName, XmlQualifiedName value, XmlQualifiedName xsiType) { 
            WriteElementQualifiedName(localName, null, value, xsiType);
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected void WriteElementQualifiedName(String localName, String ns, XmlQualifiedName value) {
            WriteElementQualifiedName(localName, ns, value, null); 
        }
 
        ///  
        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();
        }

        ///  
        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;
        }
 
        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.BaseType;
                        while (elementBaseType != null) { 
                            entry = GetTypeEntry(elementBaseType);
                            if (entry != null) break;
                            elementBaseType = elementBaseType.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(CultureInfo.InvariantCulture));
                }
                else {
                    w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + "[" + arrayLength.ToString(CultureInfo.InvariantCulture) + "]"); 
                }
                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(Res.GetString(Res.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(CultureInfo.InvariantCulture));
                }
                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(); 
        } 
        /// 
        protected void WritePotentiallyReferencingElement(string n, string ns, object o) { 
            WritePotentiallyReferencingElement(n, ns, o, null, false, false);
        }

        ///  
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType) {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, false, false); 
        } 

        ///  
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference) {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, suppressReference, false);
        }
 
        /// 
        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.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); 
                }
            } 
        } 

 
        void WriteReferencedElement(object o, Type ambientType) {
            WriteReferencedElement(null, null, o, ambientType);
        }
 
        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(); 
            }
        }

        TypeEntry GetTypeEntry(Type t) { 
            if (typeEntries == null) {
                typeEntries = new Hashtable(); 
                InitCallbacks(); 
            }
            return (TypeEntry)typeEntries[t]; 
        }

        /// 
        protected abstract void InitCallbacks(); 

        ///  
        protected void WriteReferencedElements() { 
            if (referencesToWrite == null) return;
 
            for (int i = 0; i < referencesToWrite.Count; i++) {
                WriteReferencedElement(referencesToWrite[i], null);
            }
        } 

        ///  
        protected void TopLevelElement() { 
            objectsInUse = new Hashtable();
        } 

        /// 
        ///
        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(Res.GetString(Res.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; 
        }
 
        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;
        }
    }
 

    ///  
    /// 
    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(Res.GetString(Res.XmlInternalError), "xmlMapping"); 
            if (xmlMapping is XmlTypeMapping)
                return GenerateTypeElement((XmlTypeMapping)xmlMapping); 
            else if (xmlMapping is XmlMembersMapping)
                return GenerateMembersElement((XmlMembersMapping)xmlMapping);
            else
                throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping"); 
        }
 
        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("}"); 
        }
 
        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 System.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", "); 
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")"); 
            } 

            Writer.WriteLine(");"); 

            if (hasDefault) {
                Writer.Indent--;
                Writer.WriteLine("}"); 
            }
        } 
 
        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(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace); 
            #endif
 
            Writer.Write(methodName); 
            Writer.Write("(");
            Writer.Write(source); 
            Writer.Write(")");
        }

        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(")"); 
                }
            } 
        } 

        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(Res.GetString(Res.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 System.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", "); 
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")"); 
            } 

            Writer.WriteLine(");"); 

            if (hasDefault) {
                Writer.Indent--;
                Writer.WriteLine("}"); 
            }
        } 
 
        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(");");
        }

        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(");");
        }
 
        void WriteStartElement(string name, string ns, bool writePrefixed) {
            WriteTag("WriteStartElement", name, ns, writePrefixed); 
        } 

        void WriteEndElement() { 
            Writer.WriteLine("WriteEndElement();");
        }
        void WriteEndElement(string source) {
            Writer.Write("WriteEndElement("); 
            Writer.Write(source);
            Writer.WriteLine(");"); 
        } 

        void WriteEncodedNullTag(string name, string ns) { 
            WriteTag("WriteNullTagEncoded", name, ns);
        }

        void WriteLiteralNullTag(string name, string ns) { 
            WriteTag("WriteNullTagLiteral", name, ns);
        } 
 
        void WriteEmptyTag(string name, string ns) {
            WriteTag("WriteEmptyTag", name, ns); 
        }

        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  parameter it uses  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(CultureInfo.InvariantCulture) + "])"; 
 
                    Writer.Write("if (pLength > ");
                    Writer.Write(xmlnsMember.ToString(CultureInfo.InvariantCulture)); 
                    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(CultureInfo.InvariantCulture) + "]";
 
                        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(CultureInfo.InvariantCulture) + "])";
                                    specifiedPosition = j;
                                    break; 
                                }
                            } 
                        } 

                        Writer.Write("if (pLength > "); 
                        Writer.Write(i.ToString(CultureInfo.InvariantCulture));
                        Writer.WriteLine(") {");
                        Writer.Indent++;
 
                        if (specifiedSource != null) {
                            Writer.Write("if (pLength <= "); 
                            Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture)); 
                            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(CultureInfo.InvariantCulture) + "])";
                            specifiedPosition = j; 
                            break; 
                        }
                    } 
                }

                Writer.Write("if (pLength > ");
                Writer.Write(i.ToString(CultureInfo.InvariantCulture)); 
                Writer.WriteLine(") {");
                Writer.Indent++; 
 
                if (specifiedSource != null) {
                    Writer.Write("if (pLength <= "); 
                    Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture));
                    Writer.Write(" || ");
                    Writer.Write(specifiedSource);
                    Writer.WriteLine(") {"); 
                    Writer.Indent++;
                } 
 
                string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
                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(CultureInfo.InvariantCulture) + "]";
                            else 
                                enumSource = "((" + mapping.Members[j].TypeDesc.CSharpName + ")p[" + j.ToString(CultureInfo.InvariantCulture) + "]" + ")"; 
                            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(Res.GetString(Res.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(CultureInfo.InvariantCulture));
                    Writer.WriteLine(") {");
                    Writer.Indent++;
 
                    WriteExtraMembers(mapping.Members.Length.ToString(CultureInfo.InvariantCulture), "pLength");
 
                    Writer.Indent--; 
                    Writer.WriteLine("}");
                } 
                Writer.WriteLine("WriteReferencedElements();");
            }
            Writer.Indent--;
            Writer.WriteLine("}"); 
            return methodName;
        } 
 
        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.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; 
        }

        string NextMethodName(string name) {
            return "Write" + (++NextMethodNumber).ToString(null, NumberFormatInfo.InvariantInfo) + "_" + CodeIdentifier.MakeValidInternal(name); 
        }
 
        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(CultureInfo.InvariantCulture));
                        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("}"); 
        }
 
        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 + ", " + Res.GetString(Res.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); 
            }
        } 

        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(Res.GetString(Res.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("}");
                    } 
                } 
            }
        } 

        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("}"); 
        }
 
        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); 
        }
 
        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);
            }
        } 

        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(Res.GetString(Res.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); 
            }
        } 
 
        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); 
        }
 
 
        void WriteArray(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) {
            if (elements.Length == 0 && text == null) return; 
            Writer.WriteLine("{");
            Writer.Indent++;
            string arrayTypeName = arrayTypeDesc.CSharpName;
            WriteArrayLocalDecl(arrayTypeName, "a", source, arrayTypeDesc); 
            if (arrayTypeDesc.IsNullable) {
                Writer.WriteLine("if (a != null) {"); 
                Writer.Indent++; 
            }
 
            if (choice != null) {
                bool choiceUseReflection = choice.Mapping.TypeDesc.UseReflection;
                string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
                WriteArrayLocalDecl(choiceFullName+"[]", "c", choiceSource, choice.Mapping.TypeDesc); 
                // write check for the choice identifier array
                Writer.WriteLine("if (c == null || c.Length < a.Length) {"); 
                Writer.Indent++; 
                Writer.Write("throw CreateInvalidChoiceIdentifierValueException(");
                WriteQuotedCSharpString(choice.Mapping.TypeDesc.FullName); 
                Writer.Write(", ");
                WriteQuotedCSharpString(choice.MemberName);
                Writer.Write(");");
                Writer.Indent--; 
                Writer.WriteLine("}");
            } 
 
            WriteArrayItems(elements, text, choice, arrayTypeDesc, "a", "c");
            if (arrayTypeDesc.IsNullable) { 
                Writer.Indent--;
                Writer.WriteLine("}");
            }
            Writer.Indent--; 
            Writer.WriteLine("}");
        } 
 
        void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) {
            TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; 

            if (arrayTypeDesc.IsEnumerable) {
                Writer.Write(typeof(IEnumerator).FullName);
                Writer.Write(" e = "); 
                if (arrayTypeDesc.IsPrivateImplementation) {
                    Writer.Write("(("); 
                    Writer.Write(typeof(IEnumerable).FullName); 
                    Writer.Write(")");
                    Writer.Write(arrayName); 
                    Writer.WriteLine(").GetEnumerator();");
                }
                else if(arrayTypeDesc.IsGenericInterface) {
                    if (arrayTypeDesc.UseReflection) { 
                        // we use wildcard method name for generic GetEnumerator method, so we cannot use GetStringForMethodInvoke call here
                        Writer.Write("("); 
                        Writer.Write(typeof(IEnumerator).FullName); 
                        Writer.Write(")");
                        Writer.Write(RaCodeGen.GetReflectionVariable(arrayTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*")); 
                        Writer.Write(".Invoke(");
                        Writer.Write(arrayName);
                        Writer.WriteLine(", new object[0]);");
                    } 
                    else {
                        Writer.Write("((System.Collections.Generic.IEnumerable<"); 
                        Writer.Write(arrayElementTypeDesc.CSharpName); 
                        Writer.Write(">)");
                        Writer.Write(arrayName); 
                        Writer.WriteLine(").GetEnumerator();");
                    }
                }
                else { 
                    if (arrayTypeDesc.UseReflection) {
                        Writer.Write("("); 
                        Writer.Write(typeof(IEnumerator).FullName); 
                        Writer.Write(")");
                    } 
                    Writer.Write(RaCodeGen.GetStringForMethodInvoke(arrayName, arrayTypeDesc.CSharpName, "GetEnumerator", arrayTypeDesc.UseReflection));
                    Writer.WriteLine(";");
                }
                Writer.WriteLine("if (e != null)"); 
                Writer.WriteLine("while (e.MoveNext()) {");
                Writer.Indent++; 
                string arrayTypeFullName = arrayElementTypeDesc.CSharpName; 
                WriteLocalDecl(arrayTypeFullName, arrayName+"i", "e.Current", arrayElementTypeDesc.UseReflection);
                WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, true); 
            }
            else {
                Writer.Write("for (int i");
                Writer.Write(arrayName); 
                Writer.Write(" = 0; i");
                Writer.Write(arrayName); 
                Writer.Write(" < "); 
                if (arrayTypeDesc.IsArray) {
                    Writer.Write(arrayName); 
                    Writer.Write(".Length");
                }
                else {
                    Writer.Write("(("); 
                    Writer.Write(typeof(ICollection).FullName);
                    Writer.Write(")"); 
                    Writer.Write(arrayName); 
                    Writer.Write(").Count");
                } 
                Writer.Write("; i");
                Writer.Write(arrayName);
                Writer.WriteLine("++) {");
                Writer.Indent++; 
                int count = elements.Length + (text == null ? 0 : 1);
                if (count > 1) { 
                    string arrayTypeFullName = arrayElementTypeDesc.CSharpName; 
                    WriteLocalDecl(arrayTypeFullName, arrayName+"i", RaCodeGen.GetStringForArrayMember(arrayName, "i"+arrayName, arrayTypeDesc), arrayElementTypeDesc.UseReflection);
                    if (choice != null) { 
                        string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
                        WriteLocalDecl(choiceFullName, choiceName+"i", RaCodeGen.GetStringForArrayMember(choiceName, "i"+arrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.UseReflection);
                    }
                    WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); 
                }
                else { 
                    WriteElements(RaCodeGen.GetStringForArrayMember(arrayName , "i" + arrayName, arrayTypeDesc), elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); 
                }
            } 
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        void WriteElements(string source, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) {
            WriteElements(source, null, elements, text, choice, arrayName, writeAccessors, isNullable); 
        } 

        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("}");
            }
        }
 
        void WriteText(string source, TextAccessor text) {
            if (text.Mapping is PrimitiveMapping) { 
                PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; 
                Writer.Write("WriteValue(");
                if (text.Mapping is EnumMapping) { 
                    WriteEnumValue((EnumMapping)text.Mapping, source);
                }
                else {
                    WritePrimitiveValue(mapping.TypeDesc, source, false); 
                }
                Writer.WriteLine(");"); 
            } 
            else if (text.Mapping is SpecialMapping) {
                SpecialMapping mapping = (SpecialMapping)text.Mapping; 
                switch (mapping.TypeDesc.Kind) {
                    case TypeKind.Node:
                        Writer.Write(source);
                        Writer.WriteLine(".WriteTo(Writer);"); 
                        break;
                    default: 
                        throw new InvalidOperationException(Res.GetString(Res.XmlInternalError)); 
                }
            } 
        }

        void 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(Res.GetString(Res.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(Res.GetString(Res.XmlInternalError));
            } 
        }

        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(");");
        } 

        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(")");
        } 

        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(");"); 
        }

        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++;
        } 

        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(CultureInfo.InvariantCulture));
                    Writer.Write(")"); 
                    break;
                default: 
                    if (type.IsEnum) { 
                        Writer.Write(((int)value).ToString(null, NumberFormatInfo.InvariantInfo));
                    } 
                    else {
                        throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedDefaultType, type.FullName));
                    }
                    break; 
                }
            } 
        } 

        void WriteNamespaces(string source) { 
            Writer.Write("WriteNamespaceDeclarations(");
            Writer.Write(source);
            Writer.WriteLine(");");
        } 

        int FindXmlnsIndex(MemberMapping[] members) { 
            for (int i = 0; i < members.Length; i++) { 
                if (members[i].Xmlns == null)
                    continue; 
                return i;
            }
            return -1;
        } 

        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("}");
        }

        void WriteLocalDecl(string typeName, string variableName, string initValue, bool useReflection) { 
            RaCodeGen.WriteLocalDecl(typeName, variableName, initValue, useReflection);
        } 
 
        void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
            RaCodeGen.WriteArrayLocalDecl(typeName,  variableName,  initValue,  arrayTypeDesc); 
        }
        void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection){
            RaCodeGen.WriteTypeCompare(variable, escapedTypeName, useReflection);
        } 
        void WriteInstanceOf(string source, string escapedTypeName, bool useReflection){
            RaCodeGen.WriteInstanceOf(source, escapedTypeName, useReflection); 
        } 
        void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection){
            RaCodeGen.WriteArrayTypeCompare(variable, escapedTypeName, elementTypeName, useReflection); 
        }

        void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection){
            RaCodeGen.WriteEnumCase(fullTypeName, c, useReflection); 
        }
 
        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(CultureInfo.InvariantCulture); 
                        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(CultureInfo.InvariantCulture);
                        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(Res.GetString(Res.XmlChoiceMissingAnyValue, choiceMapping.TypeDesc.FullName)); 
                }
                // Type {0} is missing value for '{1}'. 
                throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, choiceMapping.TypeDesc.FullName, element.Namespace + ":" + element.Name, element.Name, element.Namespace)); 
            }
            if(!useReflection) 
                CodeIdentifier.CheckValidIdentifier(enumValue);
            return enumValue;
        }
    } 

    internal class DynamicAssemblies { 
        private DynamicAssemblies() {} 
        static ArrayList assembliesInConfig = new ArrayList();
        static Hashtable nameToAssemblyMap; 
        static Hashtable assemblyToNameMap;
        static Hashtable tableIsTypeDynamic = new Hashtable();
        static FileIOPermission fileIOPermission;
        static FileIOPermission UnrestrictedFileIOPermission { 
            get {
                if (fileIOPermission == null) { 
                    fileIOPermission = new FileIOPermission(PermissionState.Unrestricted); 
                }
                return fileIOPermission; 
            }
        }

        // SxS: This method does not take any resource name and does not expose any resources to the caller. 
        // It's OK to suppress the SxS warning.
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)] 
        internal static bool IsTypeDynamic(Type type) {
            object oIsTypeDynamic = tableIsTypeDynamic[type]; 
            if (oIsTypeDynamic == null) {
                UnrestrictedFileIOPermission.Assert();
                Assembly assembly = type.Assembly;
                bool isTypeDynamic = assembly.IsDynamic || string.IsNullOrEmpty(assembly.Location); 
                if (!isTypeDynamic)
                { 
                    if (type.IsArray) 
                    {
                        isTypeDynamic = IsTypeDynamic(type.GetElementType()); 
                    }
                    else if (type.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;
                                } 
                            } 
                        }
                    } 
                }
                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;
        } 
 
        private static Object s_InternalSyncObject;
        private static Object InternalSyncObject { 
            get {
                if (s_InternalSyncObject == null) {
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); 
                }
                return s_InternalSyncObject; 
            } 
        }
 
        internal static void Add(Assembly a) {
            if (nameToAssemblyMap == null) {
                lock (InternalSyncObject) {
                    if (nameToAssemblyMap == null) { 
                        nameToAssemblyMap = new Hashtable();
                        assemblyToNameMap = new Hashtable(); 
                    } 
                }
            } 
            lock (nameToAssemblyMap) {
                if (assemblyToNameMap[a] != null) {
                    //already added
                    return; 
                }
                Assembly oldAssembly = 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+", "+nameToAssemblyMap.Count; 
                }
                if (key != null) { 
                    nameToAssemblyMap.Add(key, a); 
                    assemblyToNameMap.Add(a, key);
                } 
            }
        }
        internal static Assembly Get(string fullName){
            return nameToAssemblyMap!=null?(Assembly)nameToAssemblyMap[fullName]:null; 
        }
        internal static string GetName(Assembly a){ 
            return assemblyToNameMap!=null?(string)assemblyToNameMap[a]:null; 
        }
    } 
    internal class ReflectionAwareCodeGen {
        private const string hexDigits = "0123456789ABCDEF";
        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) 
        // ----------------------------------------------------------------------------------
        Hashtable reflectionVariables = null;
        int nextReflectionVariableNumber = 0;
        IndentedWriter writer; 
        internal ReflectionAwareCodeGen(IndentedWriter writer){
            this.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); 
            }
        } 
 
        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;
        } 

        void InitTheFirstTime(){
            if (reflectionVariables == null){
                reflectionVariables = new Hashtable(); 
                writer.Write(String.Format(CultureInfo.InvariantCulture, helperClassesForUseReflection,
                    "object", "string", typeof(Type).FullName, 
                    typeof(FieldInfo).FullName, typeof(PropertyInfo).FullName, 
                    typeof(MemberInfo).FullName, typeof(MemberTypes).FullName));
 
                WriteDefaultIndexerInit(typeof(IList), typeof(Array).FullName, false, false);
            }
        }
 
        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);
                }
            } 
        }
        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));
        } 

        string WriteAssemblyInfo(Type type){ 
            string assemblyFullName = type.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(type.Assembly)/*assemblyFullName*/); 
                writer.WriteLine(");"); 
                reflectionVariables.Add(assemblyFullName, assemblyVariable);
            } 
            return assemblyVariable;
        }

        string WriteMemberInfo(Type type, string escapedName, string typeVariable, string memberName){ 
            MemberInfo[] memberInfos = type.GetMember(memberName);
            for (int i = 0; i < memberInfos.Length; i++) { 
                MemberTypes memberType = memberInfos[i].MemberType; 
                if (memberType == MemberTypes.Property){
                    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 (memberType == MemberTypes.Field){ 
                    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(Res.GetString(Res.XmlSerializerUnsupportedType, memberInfos[0].ToString())); 
        }
 
        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 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(CultureInfo.InvariantCulture)); 
            }
            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);
        } 

        static string 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}}); 
            }} 
        }}
    }} 
";
    }

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Xml.Serialization { 

    using System; 
    using System.IO;
    using System.Collections;
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.Xml.Schema;
    using System.ComponentModel; 
    using System.Diagnostics; 
    using System.CodeDom.Compiler;
    using System.Globalization; 
    using System.Text;
    using System.Threading;
    using System.Security.Permissions;
    using System.Runtime.Versioning; 

    ///  
    /// 
    public abstract class XmlSerializationWriter : XmlSerializationGeneratedCode {
        XmlWriter w; 
        XmlSerializerNamespaces namespaces;
        int tempNamespacePrefix;
        Hashtable usedPrefixes;
        Hashtable references; 
        string idBase;
        int nextId; 
        Hashtable typeEntries; 
        ArrayList referencesToWrite;
        Hashtable objectsInUse; 
        string aliasBase = "q";
        bool soap12;
        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) { 
            this.w = w; 
            this.namespaces = namespaces;
            this.soap12 = (encodingStyle == Soap12.Encoding); 
            this.idBase = idBase;
            Init(tempAssembly);
        }
 
        /// 
        protected bool EscapeName { 
            get { 
                return escapeName;
            } 
            set {
                escapeName = value;
            }
        } 

        ///  
        protected XmlWriter Writer { 
            get {
                return w; 
            }
            set {
                w = value;
            } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        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);
                } 
            }
        } 
 
        /// 
        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;
        } 
 
        /// 
        /// 
        protected static Assembly ResolveDynamicAssembly(string assemblyFullName){
            return DynamicAssemblies.Get(assemblyFullName);
        }
 
        /// 
        protected static string FromByteArrayHex(byte[] value) { 
            return XmlCustomFormatter.FromByteArrayHex(value); 
        }
 
        /// 
        protected static string FromDateTime(DateTime value) {
            return XmlCustomFormatter.FromDateTime(value);
        } 

        ///  
        protected static string FromDate(DateTime value) { 
            return XmlCustomFormatter.FromDate(value);
        } 

        /// 
        protected static string FromTime(DateTime value) {
            return XmlCustomFormatter.FromTime(value); 
        }
 
        ///  
        protected static string FromChar(char value) {
            return XmlCustomFormatter.FromChar(value); 
        }

        /// 
        protected static string FromEnum(long value, string[] values, long[] ids) { 
            return XmlCustomFormatter.FromEnum(value, values, ids, null);
        } 
 
        /// 
        protected static string FromEnum(long value, string[] values, long[] ids, string typeName) { 
            return XmlCustomFormatter.FromEnum(value, values, ids, typeName);
        }

        ///  
        protected static string FromXmlName(string name) {
            return XmlCustomFormatter.FromXmlName(name); 
        } 

        ///  
        protected static string FromXmlNCName(string ncName) {
            return XmlCustomFormatter.FromXmlNCName(ncName);
        }
 
        /// 
        protected static string FromXmlNmToken(string nmToken) { 
            return XmlCustomFormatter.FromXmlNmToken(nmToken); 
        }
 
        /// 
        protected static string FromXmlNmTokens(string nmTokens) {
            return XmlCustomFormatter.FromXmlNmTokens(nmTokens);
        } 

        ///  
        protected void WriteXsiType(string name, string ns) { 
            WriteAttribute("type", XmlSchema.InstanceNamespace, GetQualifiedName(name, ns));
        } 

        XmlQualifiedName GetPrimitiveTypeName(Type type) {
            return GetPrimitiveTypeName(type, true);
        } 

        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);
        } 
 
        /// 
        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
        protected string FromXmlQualifiedName(XmlQualifiedName xmlQualifiedName) { 
            return FromXmlQualifiedName(xmlQualifiedName, true);
        } 
 
        /// 
        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);
        } 

        ///  
        protected void WriteStartElement(string name) { 
            WriteStartElement(name, null, null, false, null);
        } 

        /// 
        protected void WriteStartElement(string name, string ns) {
            WriteStartElement(name, ns, null, false, null); 
        }
 
        ///  
        protected void WriteStartElement(string name, string ns, bool writePrefixed) {
            WriteStartElement(name, ns, null, writePrefixed, null); 
        }

        /// 
        protected void WriteStartElement(string name, string ns, object o) { 
            WriteStartElement(name, ns, o, false, null);
        } 
 
        /// 
        protected void WriteStartElement(string name, string ns, object o, bool writePrefixed) { 
            WriteStartElement(name, ns, o, writePrefixed, null);
        }

        ///  
        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(Res.GetString(Res.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(Res.GetString(Res.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); 
        } 

        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;
        } 
 
        /// 
        protected void WriteNullTagEncoded(string name) { 
            WriteNullTagEncoded(name, null);
        }

        ///  
        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();
        }

        ///  
        protected void WriteNullTagLiteral(string name) {
            WriteNullTagLiteral(name, null); 
        } 

        ///  
        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(); 
        } 

        ///  
        protected void WriteEmptyTag(string name) {
            WriteEmptyTag(name, null);
        }
 
        /// 
        protected void WriteEmptyTag(string name, string ns) { 
            if (name == null || name.Length == 0) 
                return;
            WriteStartElement(name, ns, null, false); 
            w.WriteEndElement();
        }

        ///  
        protected void WriteEndElement() {
            w.WriteEndElement(); 
        } 

        ///  
        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(Res.GetString(Res.XmlInternalErrorDetails, "missing stack object of type " + o.GetType().FullName)); 
#endif
 
                objectsInUse.Remove(o);
            }
        }
 
        /// 
        protected void WriteSerializable(IXmlSerializable serializable, string name, string ns, bool isNullable) { 
            WriteSerializable(serializable, name, ns, isNullable, true); 
        }
 
        /// 
        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();
            } 
        }
 
        ///  
        protected void WriteNullableStringEncoded(string name, string ns, string value, XmlQualifiedName xsiType) {
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else
                WriteElementString(name, ns, value, xsiType);
        } 

        ///  
        protected void WriteNullableStringLiteral(string name, string ns, string value) { 
            if (value == null)
                WriteNullTagLiteral(name, ns); 
            else
                WriteElementString(name, ns, value, null);
        }
 

        ///  
        protected void WriteNullableStringEncodedRaw(string name, string ns, string value, XmlQualifiedName xsiType) { 
            if (value == null)
                WriteNullTagEncoded(name, ns); 
            else
                WriteElementStringRaw(name, ns, value, xsiType);
        }
 
        /// 
        protected void WriteNullableStringEncodedRaw(string name, string ns, byte[] value, XmlQualifiedName xsiType) { 
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else 
                WriteElementStringRaw(name, ns, value, xsiType);
        }

        ///  
        protected void WriteNullableStringLiteralRaw(string name, string ns, string value) {
            if (value == null) 
                WriteNullTagLiteral(name, ns); 
            else
                WriteElementStringRaw(name, ns, value, null); 
        }

        /// 
        protected void WriteNullableStringLiteralRaw(string name, string ns, byte[] value) { 
            if (value == null)
                WriteNullTagLiteral(name, ns); 
            else 
                WriteElementStringRaw(name, ns, value, null);
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        protected void WriteNullableQualifiedNameEncoded(string name, string ns, XmlQualifiedName value, XmlQualifiedName xsiType) { 
            if (value == null) 
                WriteNullTagEncoded(name, ns);
            else 
                WriteElementQualifiedName(name, ns, value, xsiType);
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected void WriteNullableQualifiedNameLiteral(string name, string ns, XmlQualifiedName value) {
            if (value == null) 
                WriteNullTagLiteral(name, ns);
            else
                WriteElementQualifiedName(name, ns, value, null);
        } 

 
        ///  
        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); 
        }
 
        ///  
        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(Res.GetString(Res.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(Res.GetString(Res.XmlElementNameMismatch, node.LocalName, node.NamespaceURI, name, ns));
                } 
            }
            else 
                w.WriteStartElement(name, ns); 

            node.WriteTo(w); 

            if (!any)
                w.WriteEndElement();
        } 

        ///  
        protected Exception CreateUnknownTypeException(object o) { 
            return CreateUnknownTypeException(o.GetType());
        } 

        /// 
        protected Exception CreateUnknownTypeException(Type type) {
            if (typeof(IXmlSerializable).IsAssignableFrom(type)) return new InvalidOperationException(Res.GetString(Res.XmlInvalidSerializable, type.FullName)); 
            TypeDesc typeDesc = new TypeScope().GetTypeDesc(type);
            if (!typeDesc.IsStructLike) return new InvalidOperationException(Res.GetString(Res.XmlInvalidUseOfType, type.FullName)); 
            return new InvalidOperationException(Res.GetString(Res.XmlUnxpectedType, type.FullName)); 
        }
 
        /// 
        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(Res.GetString(Res.XmlChoiceMismatchChoiceException, elementName, value, enumValue)); 
        }
 
        ///  
        protected Exception CreateUnknownAnyElementException(string name, string ns) {
            return new InvalidOperationException(Res.GetString(Res.XmlUnknownAnyElement, name, ns)); 
        }

        /// 
        protected Exception CreateInvalidChoiceIdentifierValueException(string type, string identifier) { 
            return new InvalidOperationException(Res.GetString(Res.XmlInvalidChoiceIdentifierValue, type, identifier));
        } 
 
        /// 
        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(Res.GetString(Res.XmlChoiceIdentifierMismatch, value, identifier, name, ns));
        }
 
        /// 
        protected Exception CreateInvalidEnumValueException(object value, string typeName) { 
            return new InvalidOperationException(Res.GetString(Res.XmlUnknownConstant, value, typeName)); 
        }
 
        /// 
        protected Exception CreateInvalidAnyTypeException(object o) {
            return CreateInvalidAnyTypeException(o.GetType());
        } 

        ///  
        protected Exception CreateInvalidAnyTypeException(Type type) { 
            return new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, type.FullName));
        } 

        /// 
        protected void WriteReferencingElement(string n, string ns, object o) {
            WriteReferencingElement(n, ns, o, false); 
        }
 
        ///  
        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(); 
        }

        bool IsIdDefined(object o) {
            if (references != null) return references.Contains(o); 
            else return false;
        } 
 
        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(CultureInfo.InvariantCulture); 
                references.Add(o, id); 
                if (addToReferencesList) referencesToWrite.Add(o);
            } 
            return id;
        }

        ///  
        protected void WriteId(object o) {
            WriteId(o, true); 
        } 

        void WriteId(object o, bool addToReferencesList) { 
            if (soap12)
                w.WriteAttributeString("id", Soap12.Encoding, GetId(o, addToReferencesList));
            else
                w.WriteAttributeString("id", GetId(o, addToReferencesList)); 
        }
 
        ///  
        protected void WriteXmlAttribute(XmlNode node) {
            WriteXmlAttribute(node, null); 
        }

        /// 
        protected void WriteXmlAttribute(XmlNode node, object container) { 
            XmlAttribute attr = node as XmlAttribute;
            if (attr == null) throw new InvalidOperationException(Res.GetString(Res.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;
 
                    //
                    WriteAttribute(Wsdl.ArrayType, Wsdl.Namespace, value); 
                } 
                else {
                    WriteAttribute(attr.Name, attr.NamespaceURI, attr.Value); 
                }
            }
        }
 
        /// 
        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);
                } 
            }
        }

        ///  
        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();
            }
        } 

        ///  
        protected void WriteAttribute(string localName, string value) { 
            if (value == null) return;
            w.WriteAttributeString(localName, null, value); 
        }

        /// 
        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(); 
        }

        /// 
        protected void WriteAttribute(string prefix, string localName, string ns, string value) { 
            if (value == null) return;
            w.WriteAttributeString(prefix, localName, null, value); 
        } 

        ///  
        protected void WriteValue(string value) {
            if (value == null) return;
            w.WriteString(value);
        } 

        ///  
        protected void WriteValue(byte[] value) { 
            if (value == null) return;
            XmlCustomFormatter.WriteArrayBase64(w, value, 0, value.Length); 
        }

        /// 
        protected void WriteStartDocument() { 
            if (w.WriteState == WriteState.Start) {
                w.WriteStartDocument(); 
            } 
        }
 
        /// 
        protected void WriteElementString(String localName, String value) {
            WriteElementString(localName, null, value, null);
        } 

        ///  
        protected void WriteElementString(String localName, String ns, String value) { 
            WriteElementString(localName, ns, value, null);
        } 

        /// 
        protected void WriteElementString(String localName, String value, XmlQualifiedName xsiType) {
            WriteElementString(localName, null, value, xsiType); 
        }
 
        ///  
        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(); 
            }
        } 

        /// 
        protected void WriteElementStringRaw(String localName, String value) {
            WriteElementStringRaw(localName,null,value, null); 
        }
 
        ///  
        protected void WriteElementStringRaw(String localName, byte[] value) {
            WriteElementStringRaw(localName,null,value, null); 
        }

        /// 
        protected void WriteElementStringRaw(String localName, String ns, String value) { 
            WriteElementStringRaw(localName, ns, value, null);
        } 
 
        /// 
        protected void WriteElementStringRaw(String localName, String ns, byte[] value) { 
            WriteElementStringRaw(localName, ns, value, null);
        }

        ///  
        protected void WriteElementStringRaw(String localName, String value, XmlQualifiedName xsiType) {
            WriteElementStringRaw(localName,null,value, xsiType); 
        } 

        ///  
        protected void WriteElementStringRaw(String localName, byte[] value, XmlQualifiedName xsiType) {
            WriteElementStringRaw(localName, null, value, xsiType);
        }
 
        /// 
        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();
        } 

        ///  
        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(); 
        }
 
        ///  
        protected void WriteRpcResult(string name, string ns) {
            if (!soap12) return; 
            WriteElementQualifiedName(Soap12.RpcResult, Soap12.RpcNamespace, new XmlQualifiedName(name, ns), null);
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected void WriteElementQualifiedName(String localName, XmlQualifiedName value) {
            WriteElementQualifiedName(localName,null,value, null); 
        }

        /// 
        protected void WriteElementQualifiedName(string localName, XmlQualifiedName value, XmlQualifiedName xsiType) { 
            WriteElementQualifiedName(localName, null, value, xsiType);
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected void WriteElementQualifiedName(String localName, String ns, XmlQualifiedName value) {
            WriteElementQualifiedName(localName, ns, value, null); 
        }
 
        ///  
        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();
        }

        ///  
        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;
        }
 
        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.BaseType;
                        while (elementBaseType != null) { 
                            entry = GetTypeEntry(elementBaseType);
                            if (entry != null) break;
                            elementBaseType = elementBaseType.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(CultureInfo.InvariantCulture));
                }
                else {
                    w.WriteAttributeString("arrayType", Soap.Encoding, GetQualifiedName(typeName, typeNs) + "[" + arrayLength.ToString(CultureInfo.InvariantCulture) + "]"); 
                }
                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(Res.GetString(Res.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(CultureInfo.InvariantCulture));
                }
                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(); 
        } 
        /// 
        protected void WritePotentiallyReferencingElement(string n, string ns, object o) { 
            WritePotentiallyReferencingElement(n, ns, o, null, false, false);
        }

        ///  
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType) {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, false, false); 
        } 

        ///  
        protected void WritePotentiallyReferencingElement(string n, string ns, object o, Type ambientType, bool suppressReference) {
            WritePotentiallyReferencingElement(n, ns, o, ambientType, suppressReference, false);
        }
 
        /// 
        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.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); 
                }
            } 
        } 

 
        void WriteReferencedElement(object o, Type ambientType) {
            WriteReferencedElement(null, null, o, ambientType);
        }
 
        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(); 
            }
        }

        TypeEntry GetTypeEntry(Type t) { 
            if (typeEntries == null) {
                typeEntries = new Hashtable(); 
                InitCallbacks(); 
            }
            return (TypeEntry)typeEntries[t]; 
        }

        /// 
        protected abstract void InitCallbacks(); 

        ///  
        protected void WriteReferencedElements() { 
            if (referencesToWrite == null) return;
 
            for (int i = 0; i < referencesToWrite.Count; i++) {
                WriteReferencedElement(referencesToWrite[i], null);
            }
        } 

        ///  
        protected void TopLevelElement() { 
            objectsInUse = new Hashtable();
        } 

        /// 
        ///
        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(Res.GetString(Res.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; 
        }
 
        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;
        }
    }
 

    ///  
    /// 
    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(Res.GetString(Res.XmlInternalError), "xmlMapping"); 
            if (xmlMapping is XmlTypeMapping)
                return GenerateTypeElement((XmlTypeMapping)xmlMapping); 
            else if (xmlMapping is XmlMembersMapping)
                return GenerateMembersElement((XmlMembersMapping)xmlMapping);
            else
                throw new ArgumentException(Res.GetString(Res.XmlInternalError), "xmlMapping"); 
        }
 
        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("}"); 
        }
 
        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 System.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", "); 
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")"); 
            } 

            Writer.WriteLine(");"); 

            if (hasDefault) {
                Writer.Indent--;
                Writer.WriteLine("}"); 
            }
        } 
 
        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(Res.GetString(Res.XmlInternalErrorMethod, mapping.TypeDesc.Name) + Environment.StackTrace); 
            #endif
 
            Writer.Write(methodName); 
            Writer.Write("(");
            Writer.Write(source); 
            Writer.Write(")");
        }

        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(")"); 
                }
            } 
        } 

        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(Res.GetString(Res.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 System.Xml.XmlQualifiedName(");
                WriteQuotedCSharpString(mapping.TypeName);
                Writer.Write(", "); 
                WriteQuotedCSharpString(mapping.Namespace);
                Writer.Write(")"); 
            } 

            Writer.WriteLine(");"); 

            if (hasDefault) {
                Writer.Indent--;
                Writer.WriteLine("}"); 
            }
        } 
 
        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(");");
        }

        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(");");
        }
 
        void WriteStartElement(string name, string ns, bool writePrefixed) {
            WriteTag("WriteStartElement", name, ns, writePrefixed); 
        } 

        void WriteEndElement() { 
            Writer.WriteLine("WriteEndElement();");
        }
        void WriteEndElement(string source) {
            Writer.Write("WriteEndElement("); 
            Writer.Write(source);
            Writer.WriteLine(");"); 
        } 

        void WriteEncodedNullTag(string name, string ns) { 
            WriteTag("WriteNullTagEncoded", name, ns);
        }

        void WriteLiteralNullTag(string name, string ns) { 
            WriteTag("WriteNullTagLiteral", name, ns);
        } 
 
        void WriteEmptyTag(string name, string ns) {
            WriteTag("WriteEmptyTag", name, ns); 
        }

        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  parameter it uses  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(CultureInfo.InvariantCulture) + "])"; 
 
                    Writer.Write("if (pLength > ");
                    Writer.Write(xmlnsMember.ToString(CultureInfo.InvariantCulture)); 
                    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(CultureInfo.InvariantCulture) + "]";
 
                        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(CultureInfo.InvariantCulture) + "])";
                                    specifiedPosition = j;
                                    break; 
                                }
                            } 
                        } 

                        Writer.Write("if (pLength > "); 
                        Writer.Write(i.ToString(CultureInfo.InvariantCulture));
                        Writer.WriteLine(") {");
                        Writer.Indent++;
 
                        if (specifiedSource != null) {
                            Writer.Write("if (pLength <= "); 
                            Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture)); 
                            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(CultureInfo.InvariantCulture) + "])";
                            specifiedPosition = j; 
                            break; 
                        }
                    } 
                }

                Writer.Write("if (pLength > ");
                Writer.Write(i.ToString(CultureInfo.InvariantCulture)); 
                Writer.WriteLine(") {");
                Writer.Indent++; 
 
                if (specifiedSource != null) {
                    Writer.Write("if (pLength <= "); 
                    Writer.Write(specifiedPosition.ToString(CultureInfo.InvariantCulture));
                    Writer.Write(" || ");
                    Writer.Write(specifiedSource);
                    Writer.WriteLine(") {"); 
                    Writer.Indent++;
                } 
 
                string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]";
                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(CultureInfo.InvariantCulture) + "]";
                            else 
                                enumSource = "((" + mapping.Members[j].TypeDesc.CSharpName + ")p[" + j.ToString(CultureInfo.InvariantCulture) + "]" + ")"; 
                            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(Res.GetString(Res.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(CultureInfo.InvariantCulture));
                    Writer.WriteLine(") {");
                    Writer.Indent++;
 
                    WriteExtraMembers(mapping.Members.Length.ToString(CultureInfo.InvariantCulture), "pLength");
 
                    Writer.Indent--; 
                    Writer.WriteLine("}");
                } 
                Writer.WriteLine("WriteReferencedElements();");
            }
            Writer.Indent--;
            Writer.WriteLine("}"); 
            return methodName;
        } 
 
        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.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; 
        }

        string NextMethodName(string name) {
            return "Write" + (++NextMethodNumber).ToString(null, NumberFormatInfo.InvariantInfo) + "_" + CodeIdentifier.MakeValidInternal(name); 
        }
 
        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(CultureInfo.InvariantCulture));
                        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("}"); 
        }
 
        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 + ", " + Res.GetString(Res.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); 
            }
        } 

        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(Res.GetString(Res.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("}");
                    } 
                } 
            }
        } 

        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("}"); 
        }
 
        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); 
        }
 
        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);
            }
        } 

        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(Res.GetString(Res.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); 
            }
        } 
 
        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); 
        }
 
 
        void WriteArray(string source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) {
            if (elements.Length == 0 && text == null) return; 
            Writer.WriteLine("{");
            Writer.Indent++;
            string arrayTypeName = arrayTypeDesc.CSharpName;
            WriteArrayLocalDecl(arrayTypeName, "a", source, arrayTypeDesc); 
            if (arrayTypeDesc.IsNullable) {
                Writer.WriteLine("if (a != null) {"); 
                Writer.Indent++; 
            }
 
            if (choice != null) {
                bool choiceUseReflection = choice.Mapping.TypeDesc.UseReflection;
                string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
                WriteArrayLocalDecl(choiceFullName+"[]", "c", choiceSource, choice.Mapping.TypeDesc); 
                // write check for the choice identifier array
                Writer.WriteLine("if (c == null || c.Length < a.Length) {"); 
                Writer.Indent++; 
                Writer.Write("throw CreateInvalidChoiceIdentifierValueException(");
                WriteQuotedCSharpString(choice.Mapping.TypeDesc.FullName); 
                Writer.Write(", ");
                WriteQuotedCSharpString(choice.MemberName);
                Writer.Write(");");
                Writer.Indent--; 
                Writer.WriteLine("}");
            } 
 
            WriteArrayItems(elements, text, choice, arrayTypeDesc, "a", "c");
            if (arrayTypeDesc.IsNullable) { 
                Writer.Indent--;
                Writer.WriteLine("}");
            }
            Writer.Indent--; 
            Writer.WriteLine("}");
        } 
 
        void WriteArrayItems(ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc, string arrayName, string choiceName) {
            TypeDesc arrayElementTypeDesc = arrayTypeDesc.ArrayElementTypeDesc; 

            if (arrayTypeDesc.IsEnumerable) {
                Writer.Write(typeof(IEnumerator).FullName);
                Writer.Write(" e = "); 
                if (arrayTypeDesc.IsPrivateImplementation) {
                    Writer.Write("(("); 
                    Writer.Write(typeof(IEnumerable).FullName); 
                    Writer.Write(")");
                    Writer.Write(arrayName); 
                    Writer.WriteLine(").GetEnumerator();");
                }
                else if(arrayTypeDesc.IsGenericInterface) {
                    if (arrayTypeDesc.UseReflection) { 
                        // we use wildcard method name for generic GetEnumerator method, so we cannot use GetStringForMethodInvoke call here
                        Writer.Write("("); 
                        Writer.Write(typeof(IEnumerator).FullName); 
                        Writer.Write(")");
                        Writer.Write(RaCodeGen.GetReflectionVariable(arrayTypeDesc.CSharpName, "System.Collections.Generic.IEnumerable*")); 
                        Writer.Write(".Invoke(");
                        Writer.Write(arrayName);
                        Writer.WriteLine(", new object[0]);");
                    } 
                    else {
                        Writer.Write("((System.Collections.Generic.IEnumerable<"); 
                        Writer.Write(arrayElementTypeDesc.CSharpName); 
                        Writer.Write(">)");
                        Writer.Write(arrayName); 
                        Writer.WriteLine(").GetEnumerator();");
                    }
                }
                else { 
                    if (arrayTypeDesc.UseReflection) {
                        Writer.Write("("); 
                        Writer.Write(typeof(IEnumerator).FullName); 
                        Writer.Write(")");
                    } 
                    Writer.Write(RaCodeGen.GetStringForMethodInvoke(arrayName, arrayTypeDesc.CSharpName, "GetEnumerator", arrayTypeDesc.UseReflection));
                    Writer.WriteLine(";");
                }
                Writer.WriteLine("if (e != null)"); 
                Writer.WriteLine("while (e.MoveNext()) {");
                Writer.Indent++; 
                string arrayTypeFullName = arrayElementTypeDesc.CSharpName; 
                WriteLocalDecl(arrayTypeFullName, arrayName+"i", "e.Current", arrayElementTypeDesc.UseReflection);
                WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, true); 
            }
            else {
                Writer.Write("for (int i");
                Writer.Write(arrayName); 
                Writer.Write(" = 0; i");
                Writer.Write(arrayName); 
                Writer.Write(" < "); 
                if (arrayTypeDesc.IsArray) {
                    Writer.Write(arrayName); 
                    Writer.Write(".Length");
                }
                else {
                    Writer.Write("(("); 
                    Writer.Write(typeof(ICollection).FullName);
                    Writer.Write(")"); 
                    Writer.Write(arrayName); 
                    Writer.Write(").Count");
                } 
                Writer.Write("; i");
                Writer.Write(arrayName);
                Writer.WriteLine("++) {");
                Writer.Indent++; 
                int count = elements.Length + (text == null ? 0 : 1);
                if (count > 1) { 
                    string arrayTypeFullName = arrayElementTypeDesc.CSharpName; 
                    WriteLocalDecl(arrayTypeFullName, arrayName+"i", RaCodeGen.GetStringForArrayMember(arrayName, "i"+arrayName, arrayTypeDesc), arrayElementTypeDesc.UseReflection);
                    if (choice != null) { 
                        string choiceFullName = choice.Mapping.TypeDesc.CSharpName;
                        WriteLocalDecl(choiceFullName, choiceName+"i", RaCodeGen.GetStringForArrayMember(choiceName, "i"+arrayName, choice.Mapping.TypeDesc), choice.Mapping.TypeDesc.UseReflection);
                    }
                    WriteElements(arrayName + "i", choiceName + "i", elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); 
                }
                else { 
                    WriteElements(RaCodeGen.GetStringForArrayMember(arrayName , "i" + arrayName, arrayTypeDesc), elements, text, choice, arrayName + "a", true, arrayElementTypeDesc.IsNullable); 
                }
            } 
            Writer.Indent--;
            Writer.WriteLine("}");
        }
 
        void WriteElements(string source, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) {
            WriteElements(source, null, elements, text, choice, arrayName, writeAccessors, isNullable); 
        } 

        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("}");
            }
        }
 
        void WriteText(string source, TextAccessor text) {
            if (text.Mapping is PrimitiveMapping) { 
                PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; 
                Writer.Write("WriteValue(");
                if (text.Mapping is EnumMapping) { 
                    WriteEnumValue((EnumMapping)text.Mapping, source);
                }
                else {
                    WritePrimitiveValue(mapping.TypeDesc, source, false); 
                }
                Writer.WriteLine(");"); 
            } 
            else if (text.Mapping is SpecialMapping) {
                SpecialMapping mapping = (SpecialMapping)text.Mapping; 
                switch (mapping.TypeDesc.Kind) {
                    case TypeKind.Node:
                        Writer.Write(source);
                        Writer.WriteLine(".WriteTo(Writer);"); 
                        break;
                    default: 
                        throw new InvalidOperationException(Res.GetString(Res.XmlInternalError)); 
                }
            } 
        }

        void 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(Res.GetString(Res.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(Res.GetString(Res.XmlInternalError));
            } 
        }

        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(");");
        } 

        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(")");
        } 

        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(");"); 
        }

        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++;
        } 

        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(CultureInfo.InvariantCulture));
                    Writer.Write(")"); 
                    break;
                default: 
                    if (type.IsEnum) { 
                        Writer.Write(((int)value).ToString(null, NumberFormatInfo.InvariantInfo));
                    } 
                    else {
                        throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedDefaultType, type.FullName));
                    }
                    break; 
                }
            } 
        } 

        void WriteNamespaces(string source) { 
            Writer.Write("WriteNamespaceDeclarations(");
            Writer.Write(source);
            Writer.WriteLine(");");
        } 

        int FindXmlnsIndex(MemberMapping[] members) { 
            for (int i = 0; i < members.Length; i++) { 
                if (members[i].Xmlns == null)
                    continue; 
                return i;
            }
            return -1;
        } 

        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("}");
        }

        void WriteLocalDecl(string typeName, string variableName, string initValue, bool useReflection) { 
            RaCodeGen.WriteLocalDecl(typeName, variableName, initValue, useReflection);
        } 
 
        void WriteArrayLocalDecl(string typeName, string variableName, string initValue, TypeDesc arrayTypeDesc) {
            RaCodeGen.WriteArrayLocalDecl(typeName,  variableName,  initValue,  arrayTypeDesc); 
        }
        void WriteTypeCompare(string variable, string escapedTypeName, bool useReflection){
            RaCodeGen.WriteTypeCompare(variable, escapedTypeName, useReflection);
        } 
        void WriteInstanceOf(string source, string escapedTypeName, bool useReflection){
            RaCodeGen.WriteInstanceOf(source, escapedTypeName, useReflection); 
        } 
        void WriteArrayTypeCompare(string variable, string escapedTypeName, string elementTypeName, bool useReflection){
            RaCodeGen.WriteArrayTypeCompare(variable, escapedTypeName, elementTypeName, useReflection); 
        }

        void WriteEnumCase(string fullTypeName, ConstantMapping c, bool useReflection){
            RaCodeGen.WriteEnumCase(fullTypeName, c, useReflection); 
        }
 
        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(CultureInfo.InvariantCulture); 
                        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(CultureInfo.InvariantCulture);
                        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(Res.GetString(Res.XmlChoiceMissingAnyValue, choiceMapping.TypeDesc.FullName)); 
                }
                // Type {0} is missing value for '{1}'. 
                throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, choiceMapping.TypeDesc.FullName, element.Namespace + ":" + element.Name, element.Name, element.Namespace)); 
            }
            if(!useReflection) 
                CodeIdentifier.CheckValidIdentifier(enumValue);
            return enumValue;
        }
    } 

    internal class DynamicAssemblies { 
        private DynamicAssemblies() {} 
        static ArrayList assembliesInConfig = new ArrayList();
        static Hashtable nameToAssemblyMap; 
        static Hashtable assemblyToNameMap;
        static Hashtable tableIsTypeDynamic = new Hashtable();
        static FileIOPermission fileIOPermission;
        static FileIOPermission UnrestrictedFileIOPermission { 
            get {
                if (fileIOPermission == null) { 
                    fileIOPermission = new FileIOPermission(PermissionState.Unrestricted); 
                }
                return fileIOPermission; 
            }
        }

        // SxS: This method does not take any resource name and does not expose any resources to the caller. 
        // It's OK to suppress the SxS warning.
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)] 
        internal static bool IsTypeDynamic(Type type) {
            object oIsTypeDynamic = tableIsTypeDynamic[type]; 
            if (oIsTypeDynamic == null) {
                UnrestrictedFileIOPermission.Assert();
                Assembly assembly = type.Assembly;
                bool isTypeDynamic = assembly.IsDynamic || string.IsNullOrEmpty(assembly.Location); 
                if (!isTypeDynamic)
                { 
                    if (type.IsArray) 
                    {
                        isTypeDynamic = IsTypeDynamic(type.GetElementType()); 
                    }
                    else if (type.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;
                                } 
                            } 
                        }
                    } 
                }
                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;
        } 
 
        private static Object s_InternalSyncObject;
        private static Object InternalSyncObject { 
            get {
                if (s_InternalSyncObject == null) {
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); 
                }
                return s_InternalSyncObject; 
            } 
        }
 
        internal static void Add(Assembly a) {
            if (nameToAssemblyMap == null) {
                lock (InternalSyncObject) {
                    if (nameToAssemblyMap == null) { 
                        nameToAssemblyMap = new Hashtable();
                        assemblyToNameMap = new Hashtable(); 
                    } 
                }
            } 
            lock (nameToAssemblyMap) {
                if (assemblyToNameMap[a] != null) {
                    //already added
                    return; 
                }
                Assembly oldAssembly = 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+", "+nameToAssemblyMap.Count; 
                }
                if (key != null) { 
                    nameToAssemblyMap.Add(key, a); 
                    assemblyToNameMap.Add(a, key);
                } 
            }
        }
        internal static Assembly Get(string fullName){
            return nameToAssemblyMap!=null?(Assembly)nameToAssemblyMap[fullName]:null; 
        }
        internal static string GetName(Assembly a){ 
            return assemblyToNameMap!=null?(string)assemblyToNameMap[a]:null; 
        }
    } 
    internal class ReflectionAwareCodeGen {
        private const string hexDigits = "0123456789ABCDEF";
        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) 
        // ----------------------------------------------------------------------------------
        Hashtable reflectionVariables = null;
        int nextReflectionVariableNumber = 0;
        IndentedWriter writer; 
        internal ReflectionAwareCodeGen(IndentedWriter writer){
            this.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); 
            }
        } 
 
        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;
        } 

        void InitTheFirstTime(){
            if (reflectionVariables == null){
                reflectionVariables = new Hashtable(); 
                writer.Write(String.Format(CultureInfo.InvariantCulture, helperClassesForUseReflection,
                    "object", "string", typeof(Type).FullName, 
                    typeof(FieldInfo).FullName, typeof(PropertyInfo).FullName, 
                    typeof(MemberInfo).FullName, typeof(MemberTypes).FullName));
 
                WriteDefaultIndexerInit(typeof(IList), typeof(Array).FullName, false, false);
            }
        }
 
        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);
                }
            } 
        }
        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));
        } 

        string WriteAssemblyInfo(Type type){ 
            string assemblyFullName = type.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(type.Assembly)/*assemblyFullName*/); 
                writer.WriteLine(");"); 
                reflectionVariables.Add(assemblyFullName, assemblyVariable);
            } 
            return assemblyVariable;
        }

        string WriteMemberInfo(Type type, string escapedName, string typeVariable, string memberName){ 
            MemberInfo[] memberInfos = type.GetMember(memberName);
            for (int i = 0; i < memberInfos.Length; i++) { 
                MemberTypes memberType = memberInfos[i].MemberType; 
                if (memberType == MemberTypes.Property){
                    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 (memberType == MemberTypes.Field){ 
                    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(Res.GetString(Res.XmlSerializerUnsupportedType, memberInfos[0].ToString())); 
        }
 
        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 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(CultureInfo.InvariantCulture)); 
            }
            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);
        } 

        static string 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}}); 
            }} 
        }}
    }} 
";
    }

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK