private async Task<TDictionary> UnpackToAsyncCore( Unpacker unpacker, TDictionary collection, int itemsCount, CancellationToken cancellationToken )
		{
			for ( int i = 0; i < itemsCount; i++ )
			{
				if ( !unpacker.Read() )
				{
					SerializationExceptions.ThrowMissingKey( i, unpacker );
				}

				TKey key;
				if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
				{
					key = await this._keySerializer.UnpackFromAsync( unpacker, cancellationToken ).ConfigureAwait( false );
				}
				else
				{
					using ( var subtreeUnpacker = unpacker.ReadSubtree() )
					{
						key = await this._keySerializer.UnpackFromAsync( subtreeUnpacker, cancellationToken ).ConfigureAwait( false );
					}
				}

				if ( !unpacker.Read() )
				{
					SerializationExceptions.ThrowMissingItem( i, unpacker );
				}


				TValue value;
				if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
				{
					value = await this._valueSerializer.UnpackFromAsync( unpacker, cancellationToken ).ConfigureAwait( false );
				}
				else
				{
					using ( var subtreeUnpacker = unpacker.ReadSubtree() )
					{
						value = await this._valueSerializer.UnpackFromAsync( subtreeUnpacker, cancellationToken ).ConfigureAwait( false );
					}
				}

				this.AddItem( collection, key, value );
			}

			return collection;
		}
		private void UnpackToCore( Unpacker unpacker, TDictionary collection, int itemsCount )
		{
			for ( int i = 0; i < itemsCount; i++ )
			{
				if ( !unpacker.Read() )
				{
					SerializationExceptions.ThrowMissingKey( i, unpacker );
				}

				TKey key;
				if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
				{
					key = this._keySerializer.UnpackFrom( unpacker );
				}
				else
				{
					using ( var subtreeUnpacker = unpacker.ReadSubtree() )
					{
						key = this._keySerializer.UnpackFrom( subtreeUnpacker );
					}
				}

				if ( !unpacker.Read() )
				{
					SerializationExceptions.ThrowMissingItem( i, unpacker );
				}


				TValue value;
				if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
				{
					value = this._valueSerializer.UnpackFrom( unpacker );
				}
				else
				{
					using ( var subtreeUnpacker = unpacker.ReadSubtree() )
					{
						value = this._valueSerializer.UnpackFrom( subtreeUnpacker );
					}
				}

				this.AddItem( collection, key, value );
			}
		}
        }         // UnpackAndAddCollectionItem

#if FEATURE_TAP
        protected internal override async Task <T> UnpackFromAsyncCore(Unpacker unpacker, CancellationToken cancellationToken)
        {
            object result =
                this._constructorParameters == null
                                        ? ReflectionExtensions.CreateInstancePreservingExceptionType(typeof(T))
                                        : this._constructorParameters.Select(p =>
                                                                             p.GetHasDefaultValue()
                                                ? p.DefaultValue
                                                : p.ParameterType.GetIsValueType()
                                                ? ReflectionExtensions.CreateInstancePreservingExceptionType(p.ParameterType)
                                                : null
                                                                             ).ToArray();

            var unpacked = 0;

            var asAsyncUnpackable = result as IAsyncUnpackable;

            if (asAsyncUnpackable != null)
            {
                await asAsyncUnpackable.UnpackFromMessageAsync(unpacker, cancellationToken).ConfigureAwait(false);

                return(( T )result);
            }

            var asUnpackable = result as IUnpackable;

            if (asUnpackable != null)
            {
                await Task.Run(() => asUnpackable.UnpackFromMessage(unpacker), cancellationToken).ConfigureAwait(false);

                return(( T )result);
            }

            if (unpacker.IsArrayHeader)
            {
                var itemsCount = UnpackHelpers.GetItemsCount(unpacker);

                for (int i = 0; i < itemsCount; i++)
                {
                    result = await this.UnpackMemberValueAsync(result, unpacker, itemsCount, unpacked, i, i, cancellationToken).ConfigureAwait(false);

                    unpacked++;
                }
            }
            else
            {
#if DEBUG
                Contract.Assert(unpacker.IsMapHeader, "unpacker.IsMapHeader");
#endif // DEBUG
                var itemsCount = UnpackHelpers.GetItemsCount(unpacker);

                for (int i = 0; i < itemsCount; i++)
                {
                    var name = await unpacker.ReadStringAsync(cancellationToken).ConfigureAwait(false);

                    if (!name.Success)
                    {
                        SerializationExceptions.ThrowUnexpectedEndOfStream(unpacker);
                    }

                    if (name.Value == null)
                    {
                        // missing member, drain the value and discard it.
                        if (!unpacker.Read() && i < itemsCount - 1)
                        {
                            SerializationExceptions.ThrowMissingKey(i + 1, unpacker);
                        }
                        continue;
                    }

                    int index;
                    if (!this._memberIndexes.TryGetValue(name.Value, out index))
                    {
                        // key does not exist in the object, skip the associated value
                        if (unpacker.Skip() == null)
                        {
                            SerializationExceptions.ThrowMissingItem(i, unpacker);
                        }
                        continue;
                    }

                    result = await this.UnpackMemberValueAsync(result, unpacker, itemsCount, unpacked, index, i, cancellationToken).ConfigureAwait(false);

                    unpacked++;
                }
            }

            if (this._constructorParameters == null)
            {
                return(( T )result);
            }
            else
            {
                return(ReflectionExtensions.CreateInstancePreservingExceptionType <T>(typeof(T), result as object[]));
            }
        }