void StoreCollectionValue(object collection, Type valueType, object value, CollectionDataContract collectionContract)
        {
            if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary)
            {
                ClassDataContract keyValuePairContract = DataContract.GetDataContract(valueType) as ClassDataContract;
                if (keyValuePairContract == null)
                {
                    Fx.Assert("Failed to create contract for KeyValuePair type");
                }
                DataMember keyMember   = keyValuePairContract.Members [0];
                DataMember valueMember = keyValuePairContract.Members [1];
                object     pkey        = CodeInterpreter.GetMember(keyMember.MemberInfo, value);
                object     pvalue      = CodeInterpreter.GetMember(valueMember.MemberInfo, value);

                try {
                    collectionContract.AddMethod.Invoke(collection, new object [] { pkey, pvalue });
                } catch (TargetInvocationException ex) {
                    if (ex.InnerException != null)
                    {
                        throw ex.InnerException;
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            else
            {
                collectionContract.AddMethod.Invoke(collection, new object [] { value });
            }
        }
        int ReadMembers(int index, ClassDataContract classContract, BitFlagsGenerator expectedElements, ref int memberIndex)
        {
            int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers(index, classContract.BaseContract, expectedElements,
                                                                                     ref memberIndex);

            if (memberCount <= index && index < memberCount + classContract.Members.Count)
            {
                DataMember dataMember = classContract.Members [index - memberCount];
                Type       memberType = dataMember.MemberType;

                memberIndex = memberCount;
                if (!expectedElements.Load(index))
                {
                    XmlObjectSerializerReadContextComplexJson.ThrowDuplicateMemberException(objectLocal, memberNames, memberIndex);
                }

                if (dataMember.IsGetOnlyCollection)
                {
                    var value = CodeInterpreter.GetMember(dataMember.MemberInfo, objectLocal);
                    context.StoreCollectionMemberInfo(value);
                    ReadValue(memberType, dataMember.Name);
                }
                else
                {
                    var value = ReadValue(memberType, dataMember.Name);
                    CodeInterpreter.SetMember(dataMember.MemberInfo, objectLocal, value);
                }
                memberIndex = index;
                ResetExpectedElements(expectedElements, index);
            }
            return(memberCount + classContract.Members.Count);
        }
        bool TryWritePrimitive(Type type, Func <object> value, MemberInfo memberInfo, int?arrayItemIndex, XmlDictionaryString name, int nameIndex)
        {
            PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);

            if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
            {
                return(false);
            }

            object callee = null;
            var    args   = new List <object> ();

            // load writer
            if (type.IsValueType)
            {
                callee = writer;
            }
            else
            {
                callee = context;
                args.Add(writer);
            }
            // load primitive value
            if (value != null)
            {
                args.Add(value());
            }
            else if (memberInfo != null)
            {
                args.Add(CodeInterpreter.GetMember(memberInfo, objLocal));
            }
            else
            {
                args.Add(((Array)objLocal).GetValue(new int [] { (int)arrayItemIndex }));
            }
            // load name
            if (name != null)
            {
                args.Add(name);
            }
            else
            {
                args.Add(memberNames [nameIndex]);
            }
            // load namespace
            args.Add(null);
            // call method to write primitive
            primitiveContract.XmlFormatWriterMethod.Invoke(callee, args.ToArray());
            return(true);
        }
 object LoadMemberValue(DataMember member)
 {
     return(CodeInterpreter.GetMember(member.MemberInfo, objLocal));
 }
        void WriteCollection(CollectionDataContract collectionContract)
        {
            XmlDictionaryString itemName = context.CollectionItemName;

            if (collectionContract.Kind == CollectionKind.Array)
            {
                Type itemType = collectionContract.ItemType;
                int  i;

                // This check does not exist in the original dynamic code,
                // but there is no other way to check type mismatch.
                // CollectionSerialization.ArrayContract() shows that it is required.
                if (objLocal.GetType().GetElementType() != itemType)
                {
                    throw new InvalidCastException(string.Format("Cannot cast array of {0} to array of {1}", objLocal.GetType().GetElementType(), itemType));
                }

                context.IncrementArrayCount(writer, (Array)objLocal);

                if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName))
                {
                    WriteArrayAttribute();
                    var arr = (Array)objLocal;
                    var idx = new int [1];
                    for (i = 0; i < arr.Length; i++)
                    {
                        if (!TryWritePrimitive(itemType, null, null, i, itemName, 0))
                        {
                            WriteStartElement(itemName, 0);
                            idx [0] = i;
                            var mbrVal = arr.GetValue(idx);
                            WriteValue(itemType, mbrVal);
                            WriteEndElement();
                        }
                    }
                }
            }
            else
            {
                // This check does not exist in the original dynamic code,
                // but there is no other way to check type mismatch.
                // CollectionSerialization.ArrayContract() shows that it is required.
                if (!collectionContract.UnderlyingType.IsAssignableFrom(objLocal.GetType()))
                {
                    throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", objLocal.GetType(), collectionContract.UnderlyingType));
                }

                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)
                {
                    incrementCollectionCountMethod.Invoke(context, new object [] { writer, objLocal });
                }

                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 = JsonFormatGeneratorStatics.MoveNextMethod;
                        }
                        if (getCurrentMethod == null)
                        {
                            getCurrentMethod = JsonFormatGeneratorStatics.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;
                object currentValue = null;                 // of elementType

                var enumerator = (IEnumerator)collectionContract.GetEnumeratorMethod.Invoke(objLocal, new object [0]);
                if (isDictionary)
                {
                    ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfIDictionaryEnumerator }, null);
                    enumerator = (IEnumerator)dictEnumCtor.Invoke(new object [] { enumerator });
                }
                else if (isGenericDictionary)
                {
                    Type            ctorParam    = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
                    ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
                    enumerator = (IEnumerator)Activator.CreateInstance(enumeratorType, new object [] { enumerator });
                }

                bool canWriteSimpleDictionary = isDictionary || isGenericDictionary;

                bool         writeSimpleDictionary = canWriteSimpleDictionary && context.UseSimpleDictionaryFormat;
                PropertyInfo genericDictionaryKeyProperty = null, genericDictionaryValueProperty = null;

                if (canWriteSimpleDictionary)
                {
                    Type genericDictionaryKeyValueType = Globals.TypeOfKeyValue.MakeGenericType(keyValueTypes);
                    genericDictionaryKeyProperty   = genericDictionaryKeyValueType.GetProperty(JsonGlobals.KeyString);
                    genericDictionaryValueProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.ValueString);
                }

                if (writeSimpleDictionary)
                {
                    WriteObjectAttribute();
                    object key, value;
                    var    empty_args = new object [0];
                    while ((bool)moveNextMethod.Invoke(enumerator, empty_args))
                    {
                        currentValue = getCurrentMethod.Invoke(enumerator, empty_args);
                        key          = CodeInterpreter.GetMember(genericDictionaryKeyProperty, currentValue);
                        value        = CodeInterpreter.GetMember(genericDictionaryValueProperty, currentValue);

                        WriteStartElement(key, 0 /*nameIndex*/);
                        WriteValue(genericDictionaryValueProperty.PropertyType, value);
                        WriteEndElement();
                    }
                }
                else
                {
                    WriteArrayAttribute();

                    var emptyArray = new object [0];
                    while (enumerator != null && enumerator.MoveNext())
                    {
                        currentValue = getCurrentMethod.Invoke(enumerator, emptyArray);

                        if (incrementCollectionCountMethod == null)
                        {
                            XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke(context, new object [] { 1 });
                        }

                        if (!TryWritePrimitive(elementType, () => currentValue, null, null, itemName, 0))
                        {
                            WriteStartElement(itemName, 0);
                            if (isGenericDictionary || isDictionary)
                            {
                                var jc = JsonDataContract.GetJsonDataContract(XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract(
                                                                                  collectionDataContract.ItemContract));
                                // FIXME: this TypeHandle might be wrong; there is no easy way to get Type for currentValue though.
                                DataContractJsonSerializer.WriteJsonValue(jc, writer, currentValue, context, currentValue.GetType().TypeHandle);
                            }
                            else
                            {
                                WriteValue(elementType, currentValue);
                            }
                            WriteEndElement();
                        }
                    }
                }
            }
        }