XmlFormatWriterGenerator.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 / cdf / src / WCF / Serialization / System / Runtime / Serialization / XmlFormatWriterGenerator.cs / 1305376 / XmlFormatWriterGenerator.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Runtime.Serialization
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.Security;
    using System.Security.Permissions;
    using System.Xml;
 
    #if USE_REFEMIT
    public delegate void XmlFormatClassWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context,ClassDataContract dataContract); 
    public delegate void XmlFormatCollectionWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract dataContract); 

    public sealed class XmlFormatWriterGenerator 
    #else
    internal delegate void XmlFormatClassWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context,ClassDataContract dataContract);
    internal delegate void XmlFormatCollectionWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract dataContract);
 
    internal sealed class XmlFormatWriterGenerator
    #endif 
    { 
        [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that was produced within an assert.")]
        [SecurityCritical] 
        CriticalHelper helper;

        [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.")]
        [SecurityCritical] 
        public XmlFormatWriterGenerator()
        { 
            helper = new CriticalHelper(); 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'CriticalHelper'.")]
        [SecurityCritical]
        internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract)
        { 
            return helper.GenerateClassWriter(classContract);
        } 
 
        [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'CriticalHelper'.")]
        [SecurityCritical] 
        internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
        {
            return helper.GenerateCollectionWriter(collectionContract);
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Handles all aspects of IL generation including initializing the DynamicMethod." 
            + " Changes to how IL generated could affect how data is serialized and what gets access to data," 
            + " therefore we mark it for review so that changes to generation logic are reviewed.")]
        class CriticalHelper 
        {
            CodeGenerator ilg;
            ArgBuilder xmlWriterArg;
            ArgBuilder contextArg; 
            ArgBuilder dataContractArg;
            LocalBuilder objectLocal; 
 
            // Used for classes
            LocalBuilder contractNamespacesLocal; 
            LocalBuilder memberNamesLocal;
            LocalBuilder childElementNamespacesLocal;
            int typeIndex = 1;
            int childElementIndex = 0; 

            internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract) 
            { 
                ilg = new CodeGenerator();
                bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null); 
                try
                {
                    ilg.BeginMethod("Write" + classContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatClassWriterDelegate, memberAccessFlag);
                } 
                catch (SecurityException securityException)
                { 
                    if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) 
                    {
                        classContract.RequiresMemberAccessForWrite(securityException); 
                    }
                    else
                    {
                        throw; 
                    }
                } 
                InitArgs(classContract.UnderlyingType); 
                DemandSerializationFormatterPermission(classContract);
                DemandMemberAccessPermission(memberAccessFlag); 
                WriteClass(classContract);
                return (XmlFormatClassWriterDelegate)ilg.EndMethod();
            }
 
            internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
            { 
                ilg = new CodeGenerator(); 
                bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null);
                try 
                {
                    ilg.BeginMethod("Write" + collectionContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatCollectionWriterDelegate, memberAccessFlag);
                }
                catch (SecurityException securityException) 
                {
                    if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) 
                    { 
                        collectionContract.RequiresMemberAccessForWrite(securityException);
                    } 
                    else
                    {
                        throw;
                    } 
                }
                InitArgs(collectionContract.UnderlyingType); 
                DemandMemberAccessPermission(memberAccessFlag); 
                WriteCollection(collectionContract);
                return (XmlFormatCollectionWriterDelegate)ilg.EndMethod(); 
            }

            void InitArgs(Type objType)
            { 
                xmlWriterArg = ilg.GetArg(0);
                contextArg = ilg.GetArg(2); 
                dataContractArg = ilg.GetArg(3); 

                objectLocal = ilg.DeclareLocal(objType, "objSerialized"); 
                ArgBuilder objectArg = ilg.GetArg(1);
                ilg.Load(objectArg);

                // Copy the data from the DataTimeOffset object passed in to the DateTimeOffsetAdapter. 
                // DateTimeOffsetAdapter is used here for serialization purposes to bypass the ISerializable implementation
                // on DateTimeOffset; which does not work in partial trust. 
 
                if (objType == Globals.TypeOfDateTimeOffsetAdapter)
                { 
                    ilg.ConvertValue(objectArg.ArgType, Globals.TypeOfDateTimeOffset);
                    ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetAdapterMethod);
                }
                else 
                {
                    ilg.ConvertValue(objectArg.ArgType, objType); 
                } 
                ilg.Stloc(objectLocal);
            } 

            void DemandMemberAccessPermission(bool memberAccessFlag)
            {
                if (memberAccessFlag) 
                {
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.DemandMemberAccessPermissionMethod); 
                } 
            }
 
            void DemandSerializationFormatterPermission(ClassDataContract classContract)
            {
                if (!classContract.HasDataContract && !classContract.IsNonAttributedType)
                { 
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.DemandSerializationFormatterPermissionMethod);
                } 
            } 

            void InvokeOnSerializing(ClassDataContract classContract) 
            {
                if (classContract.BaseContract != null)
                    InvokeOnSerializing(classContract.BaseContract);
                if (classContract.OnSerializing != null) 
                {
                    ilg.LoadAddress(objectLocal); 
                    ilg.Load(contextArg); 
                    ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
                    ilg.Call(classContract.OnSerializing); 
                }
            }

            void InvokeOnSerialized(ClassDataContract classContract) 
            {
                if (classContract.BaseContract != null) 
                    InvokeOnSerialized(classContract.BaseContract); 
                if (classContract.OnSerialized != null)
                { 
                    ilg.LoadAddress(objectLocal);
                    ilg.Load(contextArg);
                    ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
                    ilg.Call(classContract.OnSerialized); 
                }
            } 
 
            void WriteClass(ClassDataContract classContract)
            { 
                InvokeOnSerializing(classContract);

                if (classContract.IsISerializable)
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteISerializableMethod, xmlWriterArg, objectLocal); 
                else
                { 
                    if (classContract.ContractNamespaces.Length > 1) 
                    {
                        contractNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "contractNamespaces"); 
                        ilg.Load(dataContractArg);
                        ilg.LoadMember(XmlFormatGeneratorStatics.ContractNamespacesField);
                        ilg.Store(contractNamespacesLocal);
                    } 

                    memberNamesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "memberNames"); 
                    ilg.Load(dataContractArg); 
                    ilg.LoadMember(XmlFormatGeneratorStatics.MemberNamesField);
                    ilg.Store(memberNamesLocal); 

                    for (int i = 0; i < classContract.ChildElementNamespaces.Length; i++)
                    {
                        if (classContract.ChildElementNamespaces[i] != null) 
                        {
                            childElementNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "childElementNamespaces"); 
                            ilg.Load(dataContractArg); 
                            ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespacesProperty);
                            ilg.Store(childElementNamespacesLocal); 
                        }
                    }

                    if (classContract.HasExtensionData) 
                    {
                        LocalBuilder extensionDataLocal = ilg.DeclareLocal(Globals.TypeOfExtensionDataObject, "extensionData"); 
                        ilg.Load(objectLocal); 
                        ilg.ConvertValue(objectLocal.LocalType, Globals.TypeOfIExtensibleDataObject);
                        ilg.LoadMember(XmlFormatGeneratorStatics.ExtensionDataProperty); 
                        ilg.Store(extensionDataLocal);
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, -1);
                        WriteMembers(classContract, extensionDataLocal, classContract);
                    } 
                    else
                        WriteMembers(classContract, null, classContract); 
                } 
                InvokeOnSerialized(classContract);
            } 

            int WriteMembers(ClassDataContract classContract, LocalBuilder extensionDataLocal, ClassDataContract derivedMostClassContract)
            {
                int memberCount = (classContract.BaseContract == null) ? 0 : 
                    WriteMembers(classContract.BaseContract, extensionDataLocal, derivedMostClassContract);
 
                LocalBuilder namespaceLocal = ilg.DeclareLocal(typeof(XmlDictionaryString), "ns"); 
                if (contractNamespacesLocal == null)
                { 
                    ilg.Load(dataContractArg);
                    ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty);
                }
                else 
                    ilg.LoadArrayElement(contractNamespacesLocal, typeIndex - 1);
                ilg.Store(namespaceLocal); 
 
                ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, classContract.Members.Count);
 
                for (int i = 0; i < classContract.Members.Count; i++, memberCount++)
                {
                    DataMember member = classContract.Members[i];
                    Type memberType = member.MemberType; 
                    LocalBuilder memberValue = null;
                    if (member.IsGetOnlyCollection) 
                    { 
                        ilg.Load(contextArg);
                        ilg.Call(XmlFormatGeneratorStatics.StoreIsGetOnlyCollectionMethod); 
                    }
                    if (!member.EmitDefaultValue)
                    {
                        memberValue = LoadMemberValue(member); 
                        ilg.IfNotDefaultValue(memberValue);
                    } 
                    bool writeXsiType = CheckIfMemberHasConflict(member, classContract, derivedMostClassContract); 
                    if (writeXsiType || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, null /*arrayItemIndex*/, namespaceLocal, null /*nameLocal*/, i + childElementIndex))
                    { 
                        WriteStartElement(memberType, classContract.Namespace, namespaceLocal, null /*nameLocal*/, i + childElementIndex);
                        if (classContract.ChildElementNamespaces[i + childElementIndex] != null)
                        {
                            ilg.Load(xmlWriterArg); 
                            ilg.LoadArrayElement(childElementNamespacesLocal, i + childElementIndex);
                            ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); 
                        } 
                        if (memberValue == null)
                            memberValue = LoadMemberValue(member); 
                        WriteValue(memberValue, writeXsiType);
                        WriteEndElement();
                    }
                    if (classContract.HasExtensionData) 
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, memberCount);
                    if (!member.EmitDefaultValue) 
                    { 
                        if (member.IsRequired)
                        { 
                            ilg.Else();
                            ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMustBeEmittedMethod, member.Name, classContract.UnderlyingType);
                        }
                        ilg.EndIf(); 
                    }
 
                } 

                typeIndex++; 
                childElementIndex += classContract.Members.Count;
                return memberCount;
            }
 
            private LocalBuilder LoadMemberValue(DataMember member)
            { 
                ilg.LoadAddress(objectLocal); 
                ilg.LoadMember(member.MemberInfo);
                LocalBuilder memberValue = ilg.DeclareLocal(member.MemberType, member.Name + "Value"); 
                ilg.Stloc(memberValue);
                return memberValue;
            }
 
            void WriteCollection(CollectionDataContract collectionContract)
            { 
                LocalBuilder itemNamespace = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemNamespace"); 
                ilg.Load(dataContractArg);
                ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty); 
                ilg.Store(itemNamespace);

                LocalBuilder itemName = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName");
                ilg.Load(dataContractArg); 
                ilg.LoadMember(XmlFormatGeneratorStatics.CollectionItemNameProperty);
                ilg.Store(itemName); 
 
                if (collectionContract.ChildElementNamespace != null)
                { 
                    ilg.Load(xmlWriterArg);
                    ilg.Load(dataContractArg);
                    ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespaceProperty);
                    ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); 
                }
 
                if (collectionContract.Kind == CollectionKind.Array) 
                {
                    Type itemType = collectionContract.ItemType; 
                    LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i");

                    ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, xmlWriterArg, objectLocal);
 
                    if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, objectLocal, itemName, itemNamespace))
                    { 
                        ilg.For(i, 0, objectLocal); 
                        if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/))
                        { 
                            WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/);
                            ilg.LoadArrayElement(objectLocal, i);
                            LocalBuilder memberValue = ilg.DeclareLocal(itemType, "memberValue");
                            ilg.Stloc(memberValue); 
                            WriteValue(memberValue, false /*writeXsiType*/);
                            WriteEndElement(); 
                        } 
                        ilg.EndFor();
                    } 
                }
                else
                {
                    MethodInfo incrementCollectionCountMethod = null; 
                    switch (collectionContract.Kind)
                    { 
                        case CollectionKind.Collection: 
                        case CollectionKind.List:
                        case CollectionKind.Dictionary: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod;
                            break;
                        case CollectionKind.GenericCollection:
                        case CollectionKind.GenericList: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType);
                            break; 
                        case CollectionKind.GenericDictionary: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
                            break; 
                    }
                    if (incrementCollectionCountMethod != null)
                    {
                        ilg.Call(contextArg, incrementCollectionCountMethod, xmlWriterArg, objectLocal); 
                    }
 
                    bool isDictionary = false, isGenericDictionary = false; 
                    Type enumeratorType = null;
                    Type[] keyValueTypes = null; 
                    if (collectionContract.Kind == CollectionKind.GenericDictionary)
                    {
                        isGenericDictionary = true;
                        keyValueTypes = collectionContract.ItemType.GetGenericArguments(); 
                        enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes);
                    } 
                    else if (collectionContract.Kind == CollectionKind.Dictionary) 
                    {
                        isDictionary = true; 
                        keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
                        enumeratorType = Globals.TypeOfDictionaryEnumerator;
                    }
                    else 
                    {
                        enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; 
                    } 
                    MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
                    MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); 
                    if (moveNextMethod == null || getCurrentMethod == null)
                    {
                        if (enumeratorType.IsInterface)
                        { 
                            if (moveNextMethod == null)
                                moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; 
                            if (getCurrentMethod == null) 
                                getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod;
                        } 
                        else
                        {
                            Type ienumeratorInterface = Globals.TypeOfIEnumerator;
                            CollectionKind kind = collectionContract.Kind; 
                            if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable)
                            { 
                                Type[] interfaceTypes = enumeratorType.GetInterfaces(); 
                                foreach (Type interfaceType in interfaceTypes)
                                { 
                                    if (interfaceType.IsGenericType
                                        && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric
                                        && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType)
                                    { 
                                        ienumeratorInterface = interfaceType;
                                        break; 
                                    } 
                                }
                            } 
                            if (moveNextMethod == null)
                                moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface);
                            if (getCurrentMethod == null)
                                getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); 
                        }
                    } 
                    Type elementType = getCurrentMethod.ReturnType; 
                    LocalBuilder currentValue = ilg.DeclareLocal(elementType, "currentValue");
 
                    LocalBuilder enumerator = ilg.DeclareLocal(enumeratorType, "enumerator");
                    ilg.Call(objectLocal, collectionContract.GetEnumeratorMethod);
                    if (isDictionary)
                    { 
                        ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator);
                        ilg.New(XmlFormatGeneratorStatics.DictionaryEnumeratorCtor); 
                    } 
                    else if (isGenericDictionary)
                    { 
                        Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
                        ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
                        ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam);
                        ilg.New(dictEnumCtor); 
                    }
                    ilg.Stloc(enumerator); 
 
                    ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod);
                    if (incrementCollectionCountMethod == null) 
                    {
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
                    }
                    if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) 
                    {
                        WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); 
 
                        if (isGenericDictionary || isDictionary)
                        { 
                            ilg.Call(dataContractArg, XmlFormatGeneratorStatics.GetItemContractMethod);
                            ilg.Load(xmlWriterArg);
                            ilg.Load(currentValue);
                            ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); 
                            ilg.Load(contextArg);
                            ilg.Call(XmlFormatGeneratorStatics.WriteXmlValueMethod); 
                        } 
                        else
                        { 
                            WriteValue(currentValue, false /*writeXsiType*/);
                        }
                        WriteEndElement();
                    } 
                    ilg.EndForEach(moveNextMethod);
                } 
            } 

            bool TryWritePrimitive(Type type, LocalBuilder value, MemberInfo memberInfo, LocalBuilder arrayItemIndex, LocalBuilder ns, LocalBuilder name, int nameIndex) 
            {
                PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);
                if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
                    return false; 

                // load xmlwriter 
                if (type.IsValueType) 
                {
                    ilg.Load(xmlWriterArg); 
                }
                else
                {
                    ilg.Load(contextArg); 
                    ilg.Load(xmlWriterArg);
                } 
                // load primitive value 
                if (value != null)
                { 
                    ilg.Load(value);
                }
                else if (memberInfo != null)
                { 
                    ilg.LoadAddress(objectLocal);
                    ilg.LoadMember(memberInfo); 
                } 
                else
                { 
                    ilg.LoadArrayElement(objectLocal, arrayItemIndex);
                }
                // load name
                if (name != null) 
                {
                    ilg.Load(name); 
                } 
                else
                { 
                    ilg.LoadArrayElement(memberNamesLocal, nameIndex);
                }
                // load namespace
                ilg.Load(ns); 
                // call method to write primitive
                ilg.Call(primitiveContract.XmlFormatWriterMethod); 
                return true; 
            }
 
            bool TryWritePrimitiveArray(Type type, Type itemType, LocalBuilder value, LocalBuilder itemName, LocalBuilder itemNamespace)
            {
                PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType);
                if (primitiveContract == null) 
                    return false;
 
                string writeArrayMethod = null; 
                switch (Type.GetTypeCode(itemType))
                { 
                    case TypeCode.Boolean:
                        writeArrayMethod = "WriteBooleanArray";
                        break;
                    case TypeCode.DateTime: 
                        writeArrayMethod = "WriteDateTimeArray";
                        break; 
                    case TypeCode.Decimal: 
                        writeArrayMethod = "WriteDecimalArray";
                        break; 
                    case TypeCode.Int32:
                        writeArrayMethod = "WriteInt32Array";
                        break;
                    case TypeCode.Int64: 
                        writeArrayMethod = "WriteInt64Array";
                        break; 
                    case TypeCode.Single: 
                        writeArrayMethod = "WriteSingleArray";
                        break; 
                    case TypeCode.Double:
                        writeArrayMethod = "WriteDoubleArray";
                        break;
                    default: 
                        break;
                } 
                if (writeArrayMethod != null) 
                {
                    ilg.Load(xmlWriterArg); 
                    ilg.Load(value);
                    ilg.Load(itemName);
                    ilg.Load(itemNamespace);
                    ilg.Call(typeof(XmlWriterDelegator).GetMethod(writeArrayMethod, Globals.ScanAllMembers, null, new Type[] { type, typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null)); 
                    return true;
                } 
                return false; 
            }
 
            void WriteValue(LocalBuilder memberValue, bool writeXsiType)
            {
                Type memberType = memberValue.LocalType;
                if (memberType.IsPointer) 
                {
                    ilg.Load(memberValue); 
                    ilg.Load(memberType); 
                    ilg.Call(XmlFormatGeneratorStatics.BoxPointer);
                    memberType = Globals.TypeOfReflectionPointer; 
                    memberValue = ilg.DeclareLocal(memberType, "memberValueRefPointer");
                    ilg.Store(memberValue);
                }
                bool isNullableOfT = (memberType.IsGenericType && 
                                      memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
                if (memberType.IsValueType && !isNullableOfT) 
                { 
                    PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
                    if (primitiveContract != null && !writeXsiType) 
                        ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
                    else
                        InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, memberValue, memberType, writeXsiType);
                } 
                else
                { 
                    if (isNullableOfT) 
                    {
                        memberValue = UnwrapNullableObject(memberValue);//Leaves !HasValue on stack 
                        memberType = memberValue.LocalType;
                    }
                    else
                    { 
                        ilg.Load(memberValue);
                        ilg.Load(null); 
                        ilg.Ceq(); 
                    }
                    ilg.If(); 
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType));
                    ilg.Else();
                    PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
                    if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType) 
                    {
                        if (isNullableOfT) 
                        { 
                            ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
                        } 
                        else
                        {
                            ilg.Call(contextArg, primitiveContract.XmlFormatContentWriterMethod, xmlWriterArg, memberValue);
                        } 
                    }
                    else 
                    { 
                        if (memberType == Globals.TypeOfObject ||//boxed Nullable
                            memberType == Globals.TypeOfValueType || 
                            ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType))
                        {
                            ilg.Load(memberValue);
                            ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); 
                            memberValue = ilg.DeclareLocal(Globals.TypeOfObject, "unwrappedMemberValue");
                            memberType = memberValue.LocalType; 
                            ilg.Stloc(memberValue); 
                            ilg.If(memberValue, Cmp.EqualTo, null);
                            ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); 
                            ilg.Else();
                        }
                        InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod),
                            memberValue, memberType, writeXsiType); 

                        if (memberType == Globals.TypeOfObject) //boxed Nullable 
                            ilg.EndIf(); 
                    }
                    ilg.EndIf(); 
                }
            }

            void InternalSerialize(MethodInfo methodInfo, LocalBuilder memberValue, Type memberType, bool writeXsiType) 
            {
                ilg.Load(contextArg); 
                ilg.Load(xmlWriterArg); 
                ilg.Load(memberValue);
                ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); 
                LocalBuilder typeHandleValue = ilg.DeclareLocal(typeof(RuntimeTypeHandle), "typeHandleValue");
                ilg.Call(null, typeof(Type).GetMethod("GetTypeHandle"), memberValue);
                ilg.Stloc(typeHandleValue);
                ilg.LoadAddress(typeHandleValue); 
                ilg.Ldtoken(memberType);
                ilg.Call(typeof(RuntimeTypeHandle).GetMethod("Equals", new Type[] { typeof(RuntimeTypeHandle) })); 
                ilg.Load(writeXsiType); 
                ilg.Load(DataContract.GetId(memberType.TypeHandle));
                ilg.Ldtoken(memberType); 
                ilg.Call(methodInfo);
            }

 
            LocalBuilder UnwrapNullableObject(LocalBuilder memberValue)// Leaves !HasValue on stack
            { 
                Type memberType = memberValue.LocalType; 
                Label onNull = ilg.DefineLabel();
                Label end = ilg.DefineLabel(); 
                ilg.Load(memberValue);
                while (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable)
                {
                    Type innerType = memberType.GetGenericArguments()[0]; 
                    ilg.Dup();
                    ilg.Call(XmlFormatGeneratorStatics.GetHasValueMethod.MakeGenericMethod(innerType)); 
                    ilg.Brfalse(onNull); 
                    ilg.Call(XmlFormatGeneratorStatics.GetNullableValueMethod.MakeGenericMethod(innerType));
                    memberType = innerType; 
                }
                memberValue = ilg.DeclareLocal(memberType, "nullableUnwrappedMemberValue");
                ilg.Stloc(memberValue);
                ilg.Load(false); //isNull 
                ilg.Br(end);
                ilg.MarkLabel(onNull); 
                ilg.Pop(); 
                ilg.Call(XmlFormatGeneratorStatics.GetDefaultValueMethod.MakeGenericMethod(memberType));
                ilg.Stloc(memberValue); 
                ilg.Load(true);//isNull
                ilg.MarkLabel(end);
                return memberValue;
            } 

            bool NeedsPrefix(Type type, XmlDictionaryString ns) 
            { 
                return type == Globals.TypeOfXmlQualifiedName && (ns != null && ns.Value != null && ns.Value.Length > 0);
            } 

            void WriteStartElement(Type type, XmlDictionaryString ns, LocalBuilder namespaceLocal, LocalBuilder nameLocal, int nameIndex)
            {
                bool needsPrefix = NeedsPrefix(type, ns); 
                ilg.Load(xmlWriterArg);
                // prefix 
                if (needsPrefix) 
                    ilg.Load(Globals.ElementPrefix);
 
                // localName
                if (nameLocal == null)
                    ilg.LoadArrayElement(memberNamesLocal, nameIndex);
                else 
                    ilg.Load(nameLocal);
 
                // namespace 
                ilg.Load(namespaceLocal);
 
                ilg.Call(needsPrefix ? XmlFormatGeneratorStatics.WriteStartElementMethod3 : XmlFormatGeneratorStatics.WriteStartElementMethod2);
            }

            void WriteEndElement() 
            {
                ilg.Call(xmlWriterArg, XmlFormatGeneratorStatics.WriteEndElementMethod); 
            } 

            bool CheckIfMemberHasConflict(DataMember member, ClassDataContract classContract, ClassDataContract derivedMostClassContract) 
            {
                // Check for conflict with base type members
                if (CheckIfConflictingMembersHaveDifferentTypes(member))
                    return true; 

                // Check for conflict with derived type members 
                string name = member.Name; 
                string ns = classContract.StableName.Namespace;
                ClassDataContract currentContract = derivedMostClassContract; 
                while (currentContract != null && currentContract != classContract)
                {
                    if (ns == currentContract.StableName.Namespace)
                    { 
                        List members = currentContract.Members;
                        for (int j = 0; j < members.Count; j++) 
                        { 
                            if (name == members[j].Name)
                                return CheckIfConflictingMembersHaveDifferentTypes(members[j]); 
                        }
                    }
                    currentContract = currentContract.BaseContract;
                } 

                return false; 
            } 

            bool CheckIfConflictingMembersHaveDifferentTypes(DataMember member) 
            {
                while (member.ConflictingMember != null)
                {
                    if (member.MemberType != member.ConflictingMember.MemberType) 
                        return true;
                    member = member.ConflictingMember; 
                } 
                return false;
            } 

#if NotUsed
        static Hashtable nsToPrefixTable = new Hashtable(4);
        internal static string GetPrefix(string ns) 
        {
            string prefix = (string)nsToPrefixTable[ns]; 
            if (prefix == null) 
            {
                lock (nsToPrefixTable) 
                {
                    if (prefix == null)
                    {
                        prefix = "p" + nsToPrefixTable.Count; 
                        nsToPrefixTable.Add(ns, prefix);
                    } 
                } 
            }
            return prefix; 
        }
#endif

        } 
    }
} 
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Runtime.Serialization
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.Security;
    using System.Security.Permissions;
    using System.Xml;
 
    #if USE_REFEMIT
    public delegate void XmlFormatClassWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context,ClassDataContract dataContract); 
    public delegate void XmlFormatCollectionWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract dataContract); 

    public sealed class XmlFormatWriterGenerator 
    #else
    internal delegate void XmlFormatClassWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context,ClassDataContract dataContract);
    internal delegate void XmlFormatCollectionWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract dataContract);
 
    internal sealed class XmlFormatWriterGenerator
    #endif 
    { 
        [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that was produced within an assert.")]
        [SecurityCritical] 
        CriticalHelper helper;

        [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.")]
        [SecurityCritical] 
        public XmlFormatWriterGenerator()
        { 
            helper = new CriticalHelper(); 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'CriticalHelper'.")]
        [SecurityCritical]
        internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract)
        { 
            return helper.GenerateClassWriter(classContract);
        } 
 
        [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical helper class 'CriticalHelper'.")]
        [SecurityCritical] 
        internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
        {
            return helper.GenerateCollectionWriter(collectionContract);
        } 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Handles all aspects of IL generation including initializing the DynamicMethod." 
            + " Changes to how IL generated could affect how data is serialized and what gets access to data," 
            + " therefore we mark it for review so that changes to generation logic are reviewed.")]
        class CriticalHelper 
        {
            CodeGenerator ilg;
            ArgBuilder xmlWriterArg;
            ArgBuilder contextArg; 
            ArgBuilder dataContractArg;
            LocalBuilder objectLocal; 
 
            // Used for classes
            LocalBuilder contractNamespacesLocal; 
            LocalBuilder memberNamesLocal;
            LocalBuilder childElementNamespacesLocal;
            int typeIndex = 1;
            int childElementIndex = 0; 

            internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract) 
            { 
                ilg = new CodeGenerator();
                bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null); 
                try
                {
                    ilg.BeginMethod("Write" + classContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatClassWriterDelegate, memberAccessFlag);
                } 
                catch (SecurityException securityException)
                { 
                    if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) 
                    {
                        classContract.RequiresMemberAccessForWrite(securityException); 
                    }
                    else
                    {
                        throw; 
                    }
                } 
                InitArgs(classContract.UnderlyingType); 
                DemandSerializationFormatterPermission(classContract);
                DemandMemberAccessPermission(memberAccessFlag); 
                WriteClass(classContract);
                return (XmlFormatClassWriterDelegate)ilg.EndMethod();
            }
 
            internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
            { 
                ilg = new CodeGenerator(); 
                bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null);
                try 
                {
                    ilg.BeginMethod("Write" + collectionContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatCollectionWriterDelegate, memberAccessFlag);
                }
                catch (SecurityException securityException) 
                {
                    if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) 
                    { 
                        collectionContract.RequiresMemberAccessForWrite(securityException);
                    } 
                    else
                    {
                        throw;
                    } 
                }
                InitArgs(collectionContract.UnderlyingType); 
                DemandMemberAccessPermission(memberAccessFlag); 
                WriteCollection(collectionContract);
                return (XmlFormatCollectionWriterDelegate)ilg.EndMethod(); 
            }

            void InitArgs(Type objType)
            { 
                xmlWriterArg = ilg.GetArg(0);
                contextArg = ilg.GetArg(2); 
                dataContractArg = ilg.GetArg(3); 

                objectLocal = ilg.DeclareLocal(objType, "objSerialized"); 
                ArgBuilder objectArg = ilg.GetArg(1);
                ilg.Load(objectArg);

                // Copy the data from the DataTimeOffset object passed in to the DateTimeOffsetAdapter. 
                // DateTimeOffsetAdapter is used here for serialization purposes to bypass the ISerializable implementation
                // on DateTimeOffset; which does not work in partial trust. 
 
                if (objType == Globals.TypeOfDateTimeOffsetAdapter)
                { 
                    ilg.ConvertValue(objectArg.ArgType, Globals.TypeOfDateTimeOffset);
                    ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetAdapterMethod);
                }
                else 
                {
                    ilg.ConvertValue(objectArg.ArgType, objType); 
                } 
                ilg.Stloc(objectLocal);
            } 

            void DemandMemberAccessPermission(bool memberAccessFlag)
            {
                if (memberAccessFlag) 
                {
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.DemandMemberAccessPermissionMethod); 
                } 
            }
 
            void DemandSerializationFormatterPermission(ClassDataContract classContract)
            {
                if (!classContract.HasDataContract && !classContract.IsNonAttributedType)
                { 
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.DemandSerializationFormatterPermissionMethod);
                } 
            } 

            void InvokeOnSerializing(ClassDataContract classContract) 
            {
                if (classContract.BaseContract != null)
                    InvokeOnSerializing(classContract.BaseContract);
                if (classContract.OnSerializing != null) 
                {
                    ilg.LoadAddress(objectLocal); 
                    ilg.Load(contextArg); 
                    ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
                    ilg.Call(classContract.OnSerializing); 
                }
            }

            void InvokeOnSerialized(ClassDataContract classContract) 
            {
                if (classContract.BaseContract != null) 
                    InvokeOnSerialized(classContract.BaseContract); 
                if (classContract.OnSerialized != null)
                { 
                    ilg.LoadAddress(objectLocal);
                    ilg.Load(contextArg);
                    ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
                    ilg.Call(classContract.OnSerialized); 
                }
            } 
 
            void WriteClass(ClassDataContract classContract)
            { 
                InvokeOnSerializing(classContract);

                if (classContract.IsISerializable)
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteISerializableMethod, xmlWriterArg, objectLocal); 
                else
                { 
                    if (classContract.ContractNamespaces.Length > 1) 
                    {
                        contractNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "contractNamespaces"); 
                        ilg.Load(dataContractArg);
                        ilg.LoadMember(XmlFormatGeneratorStatics.ContractNamespacesField);
                        ilg.Store(contractNamespacesLocal);
                    } 

                    memberNamesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "memberNames"); 
                    ilg.Load(dataContractArg); 
                    ilg.LoadMember(XmlFormatGeneratorStatics.MemberNamesField);
                    ilg.Store(memberNamesLocal); 

                    for (int i = 0; i < classContract.ChildElementNamespaces.Length; i++)
                    {
                        if (classContract.ChildElementNamespaces[i] != null) 
                        {
                            childElementNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "childElementNamespaces"); 
                            ilg.Load(dataContractArg); 
                            ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespacesProperty);
                            ilg.Store(childElementNamespacesLocal); 
                        }
                    }

                    if (classContract.HasExtensionData) 
                    {
                        LocalBuilder extensionDataLocal = ilg.DeclareLocal(Globals.TypeOfExtensionDataObject, "extensionData"); 
                        ilg.Load(objectLocal); 
                        ilg.ConvertValue(objectLocal.LocalType, Globals.TypeOfIExtensibleDataObject);
                        ilg.LoadMember(XmlFormatGeneratorStatics.ExtensionDataProperty); 
                        ilg.Store(extensionDataLocal);
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, -1);
                        WriteMembers(classContract, extensionDataLocal, classContract);
                    } 
                    else
                        WriteMembers(classContract, null, classContract); 
                } 
                InvokeOnSerialized(classContract);
            } 

            int WriteMembers(ClassDataContract classContract, LocalBuilder extensionDataLocal, ClassDataContract derivedMostClassContract)
            {
                int memberCount = (classContract.BaseContract == null) ? 0 : 
                    WriteMembers(classContract.BaseContract, extensionDataLocal, derivedMostClassContract);
 
                LocalBuilder namespaceLocal = ilg.DeclareLocal(typeof(XmlDictionaryString), "ns"); 
                if (contractNamespacesLocal == null)
                { 
                    ilg.Load(dataContractArg);
                    ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty);
                }
                else 
                    ilg.LoadArrayElement(contractNamespacesLocal, typeIndex - 1);
                ilg.Store(namespaceLocal); 
 
                ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, classContract.Members.Count);
 
                for (int i = 0; i < classContract.Members.Count; i++, memberCount++)
                {
                    DataMember member = classContract.Members[i];
                    Type memberType = member.MemberType; 
                    LocalBuilder memberValue = null;
                    if (member.IsGetOnlyCollection) 
                    { 
                        ilg.Load(contextArg);
                        ilg.Call(XmlFormatGeneratorStatics.StoreIsGetOnlyCollectionMethod); 
                    }
                    if (!member.EmitDefaultValue)
                    {
                        memberValue = LoadMemberValue(member); 
                        ilg.IfNotDefaultValue(memberValue);
                    } 
                    bool writeXsiType = CheckIfMemberHasConflict(member, classContract, derivedMostClassContract); 
                    if (writeXsiType || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, null /*arrayItemIndex*/, namespaceLocal, null /*nameLocal*/, i + childElementIndex))
                    { 
                        WriteStartElement(memberType, classContract.Namespace, namespaceLocal, null /*nameLocal*/, i + childElementIndex);
                        if (classContract.ChildElementNamespaces[i + childElementIndex] != null)
                        {
                            ilg.Load(xmlWriterArg); 
                            ilg.LoadArrayElement(childElementNamespacesLocal, i + childElementIndex);
                            ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); 
                        } 
                        if (memberValue == null)
                            memberValue = LoadMemberValue(member); 
                        WriteValue(memberValue, writeXsiType);
                        WriteEndElement();
                    }
                    if (classContract.HasExtensionData) 
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, memberCount);
                    if (!member.EmitDefaultValue) 
                    { 
                        if (member.IsRequired)
                        { 
                            ilg.Else();
                            ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMustBeEmittedMethod, member.Name, classContract.UnderlyingType);
                        }
                        ilg.EndIf(); 
                    }
 
                } 

                typeIndex++; 
                childElementIndex += classContract.Members.Count;
                return memberCount;
            }
 
            private LocalBuilder LoadMemberValue(DataMember member)
            { 
                ilg.LoadAddress(objectLocal); 
                ilg.LoadMember(member.MemberInfo);
                LocalBuilder memberValue = ilg.DeclareLocal(member.MemberType, member.Name + "Value"); 
                ilg.Stloc(memberValue);
                return memberValue;
            }
 
            void WriteCollection(CollectionDataContract collectionContract)
            { 
                LocalBuilder itemNamespace = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemNamespace"); 
                ilg.Load(dataContractArg);
                ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty); 
                ilg.Store(itemNamespace);

                LocalBuilder itemName = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName");
                ilg.Load(dataContractArg); 
                ilg.LoadMember(XmlFormatGeneratorStatics.CollectionItemNameProperty);
                ilg.Store(itemName); 
 
                if (collectionContract.ChildElementNamespace != null)
                { 
                    ilg.Load(xmlWriterArg);
                    ilg.Load(dataContractArg);
                    ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespaceProperty);
                    ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); 
                }
 
                if (collectionContract.Kind == CollectionKind.Array) 
                {
                    Type itemType = collectionContract.ItemType; 
                    LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i");

                    ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, xmlWriterArg, objectLocal);
 
                    if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, objectLocal, itemName, itemNamespace))
                    { 
                        ilg.For(i, 0, objectLocal); 
                        if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/))
                        { 
                            WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/);
                            ilg.LoadArrayElement(objectLocal, i);
                            LocalBuilder memberValue = ilg.DeclareLocal(itemType, "memberValue");
                            ilg.Stloc(memberValue); 
                            WriteValue(memberValue, false /*writeXsiType*/);
                            WriteEndElement(); 
                        } 
                        ilg.EndFor();
                    } 
                }
                else
                {
                    MethodInfo incrementCollectionCountMethod = null; 
                    switch (collectionContract.Kind)
                    { 
                        case CollectionKind.Collection: 
                        case CollectionKind.List:
                        case CollectionKind.Dictionary: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod;
                            break;
                        case CollectionKind.GenericCollection:
                        case CollectionKind.GenericList: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType);
                            break; 
                        case CollectionKind.GenericDictionary: 
                            incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
                            break; 
                    }
                    if (incrementCollectionCountMethod != null)
                    {
                        ilg.Call(contextArg, incrementCollectionCountMethod, xmlWriterArg, objectLocal); 
                    }
 
                    bool isDictionary = false, isGenericDictionary = false; 
                    Type enumeratorType = null;
                    Type[] keyValueTypes = null; 
                    if (collectionContract.Kind == CollectionKind.GenericDictionary)
                    {
                        isGenericDictionary = true;
                        keyValueTypes = collectionContract.ItemType.GetGenericArguments(); 
                        enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes);
                    } 
                    else if (collectionContract.Kind == CollectionKind.Dictionary) 
                    {
                        isDictionary = true; 
                        keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
                        enumeratorType = Globals.TypeOfDictionaryEnumerator;
                    }
                    else 
                    {
                        enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; 
                    } 
                    MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
                    MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); 
                    if (moveNextMethod == null || getCurrentMethod == null)
                    {
                        if (enumeratorType.IsInterface)
                        { 
                            if (moveNextMethod == null)
                                moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; 
                            if (getCurrentMethod == null) 
                                getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod;
                        } 
                        else
                        {
                            Type ienumeratorInterface = Globals.TypeOfIEnumerator;
                            CollectionKind kind = collectionContract.Kind; 
                            if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable)
                            { 
                                Type[] interfaceTypes = enumeratorType.GetInterfaces(); 
                                foreach (Type interfaceType in interfaceTypes)
                                { 
                                    if (interfaceType.IsGenericType
                                        && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric
                                        && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType)
                                    { 
                                        ienumeratorInterface = interfaceType;
                                        break; 
                                    } 
                                }
                            } 
                            if (moveNextMethod == null)
                                moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface);
                            if (getCurrentMethod == null)
                                getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); 
                        }
                    } 
                    Type elementType = getCurrentMethod.ReturnType; 
                    LocalBuilder currentValue = ilg.DeclareLocal(elementType, "currentValue");
 
                    LocalBuilder enumerator = ilg.DeclareLocal(enumeratorType, "enumerator");
                    ilg.Call(objectLocal, collectionContract.GetEnumeratorMethod);
                    if (isDictionary)
                    { 
                        ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator);
                        ilg.New(XmlFormatGeneratorStatics.DictionaryEnumeratorCtor); 
                    } 
                    else if (isGenericDictionary)
                    { 
                        Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
                        ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
                        ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam);
                        ilg.New(dictEnumCtor); 
                    }
                    ilg.Stloc(enumerator); 
 
                    ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod);
                    if (incrementCollectionCountMethod == null) 
                    {
                        ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
                    }
                    if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) 
                    {
                        WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); 
 
                        if (isGenericDictionary || isDictionary)
                        { 
                            ilg.Call(dataContractArg, XmlFormatGeneratorStatics.GetItemContractMethod);
                            ilg.Load(xmlWriterArg);
                            ilg.Load(currentValue);
                            ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); 
                            ilg.Load(contextArg);
                            ilg.Call(XmlFormatGeneratorStatics.WriteXmlValueMethod); 
                        } 
                        else
                        { 
                            WriteValue(currentValue, false /*writeXsiType*/);
                        }
                        WriteEndElement();
                    } 
                    ilg.EndForEach(moveNextMethod);
                } 
            } 

            bool TryWritePrimitive(Type type, LocalBuilder value, MemberInfo memberInfo, LocalBuilder arrayItemIndex, LocalBuilder ns, LocalBuilder name, int nameIndex) 
            {
                PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);
                if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
                    return false; 

                // load xmlwriter 
                if (type.IsValueType) 
                {
                    ilg.Load(xmlWriterArg); 
                }
                else
                {
                    ilg.Load(contextArg); 
                    ilg.Load(xmlWriterArg);
                } 
                // load primitive value 
                if (value != null)
                { 
                    ilg.Load(value);
                }
                else if (memberInfo != null)
                { 
                    ilg.LoadAddress(objectLocal);
                    ilg.LoadMember(memberInfo); 
                } 
                else
                { 
                    ilg.LoadArrayElement(objectLocal, arrayItemIndex);
                }
                // load name
                if (name != null) 
                {
                    ilg.Load(name); 
                } 
                else
                { 
                    ilg.LoadArrayElement(memberNamesLocal, nameIndex);
                }
                // load namespace
                ilg.Load(ns); 
                // call method to write primitive
                ilg.Call(primitiveContract.XmlFormatWriterMethod); 
                return true; 
            }
 
            bool TryWritePrimitiveArray(Type type, Type itemType, LocalBuilder value, LocalBuilder itemName, LocalBuilder itemNamespace)
            {
                PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType);
                if (primitiveContract == null) 
                    return false;
 
                string writeArrayMethod = null; 
                switch (Type.GetTypeCode(itemType))
                { 
                    case TypeCode.Boolean:
                        writeArrayMethod = "WriteBooleanArray";
                        break;
                    case TypeCode.DateTime: 
                        writeArrayMethod = "WriteDateTimeArray";
                        break; 
                    case TypeCode.Decimal: 
                        writeArrayMethod = "WriteDecimalArray";
                        break; 
                    case TypeCode.Int32:
                        writeArrayMethod = "WriteInt32Array";
                        break;
                    case TypeCode.Int64: 
                        writeArrayMethod = "WriteInt64Array";
                        break; 
                    case TypeCode.Single: 
                        writeArrayMethod = "WriteSingleArray";
                        break; 
                    case TypeCode.Double:
                        writeArrayMethod = "WriteDoubleArray";
                        break;
                    default: 
                        break;
                } 
                if (writeArrayMethod != null) 
                {
                    ilg.Load(xmlWriterArg); 
                    ilg.Load(value);
                    ilg.Load(itemName);
                    ilg.Load(itemNamespace);
                    ilg.Call(typeof(XmlWriterDelegator).GetMethod(writeArrayMethod, Globals.ScanAllMembers, null, new Type[] { type, typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null)); 
                    return true;
                } 
                return false; 
            }
 
            void WriteValue(LocalBuilder memberValue, bool writeXsiType)
            {
                Type memberType = memberValue.LocalType;
                if (memberType.IsPointer) 
                {
                    ilg.Load(memberValue); 
                    ilg.Load(memberType); 
                    ilg.Call(XmlFormatGeneratorStatics.BoxPointer);
                    memberType = Globals.TypeOfReflectionPointer; 
                    memberValue = ilg.DeclareLocal(memberType, "memberValueRefPointer");
                    ilg.Store(memberValue);
                }
                bool isNullableOfT = (memberType.IsGenericType && 
                                      memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
                if (memberType.IsValueType && !isNullableOfT) 
                { 
                    PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
                    if (primitiveContract != null && !writeXsiType) 
                        ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
                    else
                        InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, memberValue, memberType, writeXsiType);
                } 
                else
                { 
                    if (isNullableOfT) 
                    {
                        memberValue = UnwrapNullableObject(memberValue);//Leaves !HasValue on stack 
                        memberType = memberValue.LocalType;
                    }
                    else
                    { 
                        ilg.Load(memberValue);
                        ilg.Load(null); 
                        ilg.Ceq(); 
                    }
                    ilg.If(); 
                    ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType));
                    ilg.Else();
                    PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
                    if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType) 
                    {
                        if (isNullableOfT) 
                        { 
                            ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
                        } 
                        else
                        {
                            ilg.Call(contextArg, primitiveContract.XmlFormatContentWriterMethod, xmlWriterArg, memberValue);
                        } 
                    }
                    else 
                    { 
                        if (memberType == Globals.TypeOfObject ||//boxed Nullable
                            memberType == Globals.TypeOfValueType || 
                            ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType))
                        {
                            ilg.Load(memberValue);
                            ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); 
                            memberValue = ilg.DeclareLocal(Globals.TypeOfObject, "unwrappedMemberValue");
                            memberType = memberValue.LocalType; 
                            ilg.Stloc(memberValue); 
                            ilg.If(memberValue, Cmp.EqualTo, null);
                            ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); 
                            ilg.Else();
                        }
                        InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod),
                            memberValue, memberType, writeXsiType); 

                        if (memberType == Globals.TypeOfObject) //boxed Nullable 
                            ilg.EndIf(); 
                    }
                    ilg.EndIf(); 
                }
            }

            void InternalSerialize(MethodInfo methodInfo, LocalBuilder memberValue, Type memberType, bool writeXsiType) 
            {
                ilg.Load(contextArg); 
                ilg.Load(xmlWriterArg); 
                ilg.Load(memberValue);
                ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); 
                LocalBuilder typeHandleValue = ilg.DeclareLocal(typeof(RuntimeTypeHandle), "typeHandleValue");
                ilg.Call(null, typeof(Type).GetMethod("GetTypeHandle"), memberValue);
                ilg.Stloc(typeHandleValue);
                ilg.LoadAddress(typeHandleValue); 
                ilg.Ldtoken(memberType);
                ilg.Call(typeof(RuntimeTypeHandle).GetMethod("Equals", new Type[] { typeof(RuntimeTypeHandle) })); 
                ilg.Load(writeXsiType); 
                ilg.Load(DataContract.GetId(memberType.TypeHandle));
                ilg.Ldtoken(memberType); 
                ilg.Call(methodInfo);
            }

 
            LocalBuilder UnwrapNullableObject(LocalBuilder memberValue)// Leaves !HasValue on stack
            { 
                Type memberType = memberValue.LocalType; 
                Label onNull = ilg.DefineLabel();
                Label end = ilg.DefineLabel(); 
                ilg.Load(memberValue);
                while (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable)
                {
                    Type innerType = memberType.GetGenericArguments()[0]; 
                    ilg.Dup();
                    ilg.Call(XmlFormatGeneratorStatics.GetHasValueMethod.MakeGenericMethod(innerType)); 
                    ilg.Brfalse(onNull); 
                    ilg.Call(XmlFormatGeneratorStatics.GetNullableValueMethod.MakeGenericMethod(innerType));
                    memberType = innerType; 
                }
                memberValue = ilg.DeclareLocal(memberType, "nullableUnwrappedMemberValue");
                ilg.Stloc(memberValue);
                ilg.Load(false); //isNull 
                ilg.Br(end);
                ilg.MarkLabel(onNull); 
                ilg.Pop(); 
                ilg.Call(XmlFormatGeneratorStatics.GetDefaultValueMethod.MakeGenericMethod(memberType));
                ilg.Stloc(memberValue); 
                ilg.Load(true);//isNull
                ilg.MarkLabel(end);
                return memberValue;
            } 

            bool NeedsPrefix(Type type, XmlDictionaryString ns) 
            { 
                return type == Globals.TypeOfXmlQualifiedName && (ns != null && ns.Value != null && ns.Value.Length > 0);
            } 

            void WriteStartElement(Type type, XmlDictionaryString ns, LocalBuilder namespaceLocal, LocalBuilder nameLocal, int nameIndex)
            {
                bool needsPrefix = NeedsPrefix(type, ns); 
                ilg.Load(xmlWriterArg);
                // prefix 
                if (needsPrefix) 
                    ilg.Load(Globals.ElementPrefix);
 
                // localName
                if (nameLocal == null)
                    ilg.LoadArrayElement(memberNamesLocal, nameIndex);
                else 
                    ilg.Load(nameLocal);
 
                // namespace 
                ilg.Load(namespaceLocal);
 
                ilg.Call(needsPrefix ? XmlFormatGeneratorStatics.WriteStartElementMethod3 : XmlFormatGeneratorStatics.WriteStartElementMethod2);
            }

            void WriteEndElement() 
            {
                ilg.Call(xmlWriterArg, XmlFormatGeneratorStatics.WriteEndElementMethod); 
            } 

            bool CheckIfMemberHasConflict(DataMember member, ClassDataContract classContract, ClassDataContract derivedMostClassContract) 
            {
                // Check for conflict with base type members
                if (CheckIfConflictingMembersHaveDifferentTypes(member))
                    return true; 

                // Check for conflict with derived type members 
                string name = member.Name; 
                string ns = classContract.StableName.Namespace;
                ClassDataContract currentContract = derivedMostClassContract; 
                while (currentContract != null && currentContract != classContract)
                {
                    if (ns == currentContract.StableName.Namespace)
                    { 
                        List members = currentContract.Members;
                        for (int j = 0; j < members.Count; j++) 
                        { 
                            if (name == members[j].Name)
                                return CheckIfConflictingMembersHaveDifferentTypes(members[j]); 
                        }
                    }
                    currentContract = currentContract.BaseContract;
                } 

                return false; 
            } 

            bool CheckIfConflictingMembersHaveDifferentTypes(DataMember member) 
            {
                while (member.ConflictingMember != null)
                {
                    if (member.MemberType != member.ConflictingMember.MemberType) 
                        return true;
                    member = member.ConflictingMember; 
                } 
                return false;
            } 

#if NotUsed
        static Hashtable nsToPrefixTable = new Hashtable(4);
        internal static string GetPrefix(string ns) 
        {
            string prefix = (string)nsToPrefixTable[ns]; 
            if (prefix == null) 
            {
                lock (nsToPrefixTable) 
                {
                    if (prefix == null)
                    {
                        prefix = "p" + nsToPrefixTable.Count; 
                        nsToPrefixTable.Add(ns, prefix);
                    } 
                } 
            }
            return prefix; 
        }
#endif

        } 
    }
} 
 


// 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