public SerializerCapabilities GetCapabilitiesForCollection(CollectionTraits traits)
 {
     return
         (!this.CanDeserialize
                                 ? SerializerCapabilities.PackTo
                                 : traits.AddMethod == null
                                         ? (SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom)
                                         : (SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom | SerializerCapabilities.UnpackTo));
 }
Example #2
0
        private static bool TryCreateCollectionTraitsForIEnumerableT(
            Type source,
            GenericCollectionTypes genericTypes,
            CollectionTraitOptions options,
            MethodInfo getMethod,
            out CollectionTraits result
            )
        {
            var elementType = genericTypes.IEnumerableT.GetGenericArguments()[0];
            var addMethod   = GetAddMethod(source, elementType, options);

            if (addMethod == null && ((options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes) != 0))
            {
                // This should be non collection object isntead of "unappendable" collection.
                result = default(CollectionTraits);
                return(false);
            }

            CollectionDetailedKind kind = CollectionDetailedKind.GenericEnumerable;

            if (genericTypes.IListT != null)
            {
                kind = CollectionDetailedKind.GenericList;
            }
#if !NETFX_35 && !UNITY
            else if (genericTypes.ISetT != null)
            {
                kind = CollectionDetailedKind.GenericSet;
            }
#endif // !NETFX_35 && !UNITY
            else if (genericTypes.ICollectionT != null)
            {
                kind = CollectionDetailedKind.GenericCollection;
            }
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
            else if (genericTypes.IReadOnlyListT != null)
            {
                kind = CollectionDetailedKind.GenericReadOnlyList;
            }
            else if (genericTypes.IReadOnlyCollectionT != null)
            {
                kind = CollectionDetailedKind.GenericReadOnlyCollection;
            }
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )

            result =
                new CollectionTraits(
                    kind,
                    elementType,
                    getMethod ?? GetGetEnumeratorMethodFromElementType(source, elementType, options),
                    addMethod,
                    GetCountGetterMethod(source, elementType, options)
                    );
            return(true);
        }
        private static bool TryCreateGenericCollectionTraits(Type source, Type type, out CollectionTraits result)
        {
            if (type == typeof(IDictionary <MessagePackObject, MessagePackObject>))
            {
                result = new CollectionTraits(
                    CollectionDetailedKind.GenericDictionary,
                    GetAddMethod(source, typeof(MessagePackObject), typeof(MessagePackObject)),
                    GetCountGetterMethod(source, typeof(KeyValuePair <MessagePackObject, MessagePackObject>)),
                    FindInterfaceMethod(
                        source,
                        typeof(IEnumerable <KeyValuePair <MessagePackObject, MessagePackObject> >),
                        "GetEnumerator",
                        ReflectionAbstractions.EmptyTypes
                        ),
                    typeof(KeyValuePair <MessagePackObject, MessagePackObject>)
                    );

                return(true);
            }

            if (type == typeof(IEnumerable <MessagePackObject>))
            {
                var addMethod = GetAddMethod(source, typeof(MessagePackObject));
                if (addMethod != null)
                {
                    {
                        result = new CollectionTraits(
                            (source == typeof(IList <MessagePackObject>) || source.Implements(typeof(IList <MessagePackObject>)))
                                                        ? CollectionDetailedKind.GenericList
#if !NETFX_35 && !UNITY
                                                        : (source == typeof(ISet <MessagePackObject>) || source.Implements(typeof(ISet <MessagePackObject>)))
                                                        ? CollectionDetailedKind.GenericSet
#endif // !NETFX_35 && !UNITY
                                                        : (source == typeof(ICollection <MessagePackObject>) ||
                                                           source.Implements(typeof(ICollection <MessagePackObject>)))
                                                        ? CollectionDetailedKind.GenericCollection
                                                        : CollectionDetailedKind.GenericEnumerable,
                            addMethod,
                            GetCountGetterMethod(source, typeof(MessagePackObject)),
                            FindInterfaceMethod(
                                source,
                                typeof(IEnumerable <MessagePackObject>),
                                "GetEnumerator",
                                ReflectionAbstractions.EmptyTypes
                                ),
                            typeof(MessagePackObject)
                            );
                        return(true);
                    }
                }
            }

            result = default(CollectionTraits);
            return(false);
        }
Example #4
0
        internal static bool IsReadOnlyAppendableCollectionMember(MemberInfo memberInfo)
        {
            Contract.Requires(memberInfo != null);
            if (memberInfo.CanSetValue())
            {
                return(false);
            }
            Type memberValueType = memberInfo.GetMemberValueType();

            if (memberValueType.IsArray)
            {
                return(false);
            }
            CollectionTraits collectionTraits = memberValueType.GetCollectionTraits();

            return((collectionTraits.CollectionType != CollectionKind.NotCollection) && (collectionTraits.AddMethod != null));
        }
Example #5
0
        private static bool TryCreateCollectionTraitsForHasGetEnumeratorType(
            Type source,
            CollectionTraitOptions options,
            MethodInfo getEnumerator,
            out CollectionTraits result
            )
        {
            if (source.Implements(typeof(IDictionary <,>))
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                || source.Implements(typeof(IReadOnlyDictionary <,>))
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
                )
            {
                var ienumetaorT =
                    getEnumerator.ReturnType.GetInterfaces()
                    .FirstOrDefault(@interface =>
                                    @interface.GetIsGenericType() && @interface.GetGenericTypeDefinition() == typeof(IEnumerator <>)
                                    );
                if (ienumetaorT != null)
                {
                    var elementType = ienumetaorT.GetGenericArguments()[0];
                    var elementTypeGenericArguments = elementType.GetGenericArguments();

                    result =
                        new CollectionTraits(
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                            source.Implements(typeof(IDictionary <,>))
                                                        ? CollectionDetailedKind.GenericDictionary
                                                        : CollectionDetailedKind.GenericReadOnlyDictionary,
#else
                            CollectionDetailedKind.GenericDictionary,
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
                            elementType,
                            getEnumerator,
                            GetAddMethod(source, elementTypeGenericArguments[0], elementTypeGenericArguments [1], options),
                            GetCountGetterMethod(source, elementType, options)
                            );

                    return(true);
                }
            }

            if (source.IsAssignableTo(typeof(IDictionary)))
            {
                result =
                    new CollectionTraits(
                        CollectionDetailedKind.NonGenericDictionary,
                        typeof(DictionaryEntry),
                        getEnumerator,
                        GetAddMethod(source, typeof(object), typeof(object), options),
                        GetCountGetterMethod(source, typeof(object), options)
                        );

                return(true);
            }

            // Block to limit variable scope
            {
                var ienumetaorT =
                    IsIEnumeratorT(getEnumerator.ReturnType)
                                        ? getEnumerator.ReturnType
                                        : getEnumerator.ReturnType.GetInterfaces().FirstOrDefault(IsIEnumeratorT);

                if (ienumetaorT != null)
                {
                    // Get the open generic types once
                    Type[] genericInterfaces =
                        source.GetInterfaces()
                        .Where(i => i.GetIsGenericType())
                        .Select(i => i.GetGenericTypeDefinition())
                        .ToArray();

                    var genericTypes = new GenericCollectionTypes();
                    genericTypes.IEnumerableT = ienumetaorT;
                    genericTypes.ICollectionT = genericInterfaces.FirstOrDefault(i => i == typeof(ICollection <>));
                    genericTypes.IListT       = genericInterfaces.FirstOrDefault(i => i == typeof(IList <>));

#if !NETFX_35 && !UNITY
                    genericTypes.ISetT = genericInterfaces.FirstOrDefault(i => i == typeof(ISet <>));
#endif // !NETFX_35 && !UNITY
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                    genericTypes.IReadOnlyCollectionT = genericInterfaces.FirstOrDefault(i => i == typeof(IReadOnlyCollection <>));
                    genericTypes.IReadOnlyListT       = genericInterfaces.FirstOrDefault(i => i == typeof(IReadOnlyList <>));
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )

                    return(TryCreateCollectionTraitsForIEnumerableT(source, genericTypes, options, getEnumerator, out result));
                }
            }

            result = default(CollectionTraits);
            return(false);
        }
		private static bool TryCreateGenericCollectionTraits( Type source, Type type, CollectionTraitOptions options, out CollectionTraits result )
		{
			if ( type == typeof( IDictionary<MessagePackObject, MessagePackObject> )
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
				|| type == typeof( IReadOnlyDictionary<MessagePackObject, MessagePackObject> )
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
			)
			{
				result = 
					new CollectionTraits(
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
						( source == typeof( IDictionary<MessagePackObject, MessagePackObject> ) || source.Implements( typeof( IDictionary<MessagePackObject, MessagePackObject> ) ) )
							? CollectionDetailedKind.GenericDictionary
							: CollectionDetailedKind.GenericReadOnlyDictionary,
#else
						CollectionDetailedKind.GenericDictionary,
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
						typeof( KeyValuePair<MessagePackObject, MessagePackObject> ),
						GetGetEnumeratorMethodFromEnumerableType( source, typeof( IEnumerable<KeyValuePair<MessagePackObject, MessagePackObject>> ), options ),
						GetAddMethod( source, typeof( MessagePackObject ), typeof( MessagePackObject ), options ),
						GetCountGetterMethod( source, typeof( KeyValuePair<MessagePackObject, MessagePackObject> ), options )
					);

				return true;
			}

			if ( type == typeof( IEnumerable<MessagePackObject> ) )
			{
				var addMethod = GetAddMethod( source, typeof( MessagePackObject ), options | CollectionTraitOptions.WithAddMethod );
				if ( addMethod != null )
				{
					{
						result = 
							new CollectionTraits(
								( source == typeof( IList<MessagePackObject> ) || source.Implements( typeof( IList<MessagePackObject> ) ) )
									? CollectionDetailedKind.GenericList
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
									: ( source == typeof( IReadOnlyList<MessagePackObject> ) || source.Implements( typeof( IReadOnlyList<MessagePackObject> ) ) )
										? CollectionDetailedKind.GenericReadOnlyList
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
#if !NETFX_35 && !UNITY
										: ( source == typeof( ISet<MessagePackObject> ) || source.Implements( typeof( ISet<MessagePackObject> ) ) )
											? CollectionDetailedKind.GenericSet
#endif // !NETFX_35 && !UNITY
											: ( source == typeof( ICollection<MessagePackObject> ) ||
												source.Implements( typeof( ICollection<MessagePackObject> ) ) )
												? CollectionDetailedKind.GenericCollection
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
												: ( source == typeof( IReadOnlyCollection<MessagePackObject> ) || source.Implements( typeof( IReadOnlyCollection<MessagePackObject> ) ) )
													? CollectionDetailedKind.GenericReadOnlyCollection
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
													: CollectionDetailedKind.GenericEnumerable,
								typeof( MessagePackObject ),
								GetGetEnumeratorMethodFromEnumerableType( source, typeof( IEnumerable<MessagePackObject> ), options ),
								addMethod,
								GetCountGetterMethod( source, typeof( MessagePackObject ), options )
							);

						return true;
					}
				}
			}

			result = default( CollectionTraits );
			return false;
		}
		private static bool TryCreateCollectionTraitsForHasGetEnumeratorType(
			Type source,
			CollectionTraitOptions options,
			MethodInfo getEnumerator,
			out CollectionTraits result
		)
		{
			if ( source.Implements( typeof( IDictionary<,> ) )
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
				|| source.Implements( typeof( IReadOnlyDictionary<,> ) )
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
			)
			{
				var ienumetaorT =
					getEnumerator.ReturnType.GetInterfaces()
						.FirstOrDefault( @interface => 
												@interface.GetIsGenericType() && @interface.GetGenericTypeDefinition() == typeof( IEnumerator<> ) 
						);
				if ( ienumetaorT != null )
				{
					var elementType = ienumetaorT.GetGenericArguments()[ 0 ];
					var elementTypeGenericArguments = elementType.GetGenericArguments();

					result = 
						new CollectionTraits(
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
							source.Implements( typeof( IDictionary<,> ) )
								? CollectionDetailedKind.GenericDictionary
								: CollectionDetailedKind.GenericReadOnlyDictionary,
#else
							CollectionDetailedKind.GenericDictionary,
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
							elementType,
							getEnumerator,
							GetAddMethod( source, elementTypeGenericArguments[ 0 ], elementTypeGenericArguments [ 1 ], options ),
							GetCountGetterMethod( source, elementType, options )
						);

					return true;
				}
			}

			if ( source.IsAssignableTo( typeof( IDictionary ) ) )
			{
				result = 
					new CollectionTraits(
						CollectionDetailedKind.NonGenericDictionary,
						typeof( DictionaryEntry ),
						getEnumerator,
						GetAddMethod( source, typeof( object ), typeof( object ), options ),
						GetCountGetterMethod( source, typeof( object ), options )
					);

				return true;
			}

			// Block to limit variable scope
			{
				var ienumetaorT =
					IsIEnumeratorT( getEnumerator.ReturnType )
						? getEnumerator.ReturnType
						: getEnumerator.ReturnType.GetInterfaces().FirstOrDefault( IsIEnumeratorT );

				if ( ienumetaorT != null )
				{
					// Get the open generic types once
					Type[] genericInterfaces =
						source.GetInterfaces()
							.Where( i => i.GetIsGenericType() )
							.Select( i => i.GetGenericTypeDefinition() )
							.ToArray();

					var genericTypes = new GenericCollectionTypes();
					genericTypes.IEnumerableT = ienumetaorT;
					genericTypes.ICollectionT = genericInterfaces.FirstOrDefault( i => i == typeof(ICollection<>) );
					genericTypes.IListT = genericInterfaces.FirstOrDefault( i => i == typeof(IList<>) );

#if !NETFX_35 && !UNITY
					genericTypes.ISetT = genericInterfaces.FirstOrDefault( i => i == typeof(ISet<>) );
#endif // !NETFX_35 && !UNITY
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
					genericTypes.IReadOnlyCollectionT = genericInterfaces.FirstOrDefault( i => i == typeof(IReadOnlyCollection<>) );
					genericTypes.IReadOnlyListT = genericInterfaces.FirstOrDefault( i => i == typeof(IReadOnlyList<>) );
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )

					return TryCreateCollectionTraitsForIEnumerableT( source, genericTypes, options, getEnumerator, out result );
				}
			}

			result = default( CollectionTraits );
			return false;
		}
Example #8
0
		/// <summary>
		///		Emits 'foreach' statement on the IL stream.
		/// </summary>
		/// <param name="il">IL generator to be emitted to.</param>
		/// <param name="traits"><see cref="CollectionTraits"/> which contains traits of the iterating collection.</param>
		/// <param name="collection">'collection' argument index.</param>
		/// <param name="bodyEmitter">Delegate to emit body statement.</param>
		public static void EmitForEach( TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action<TracingILGenerator, Action> bodyEmitter )
		{
			Contract.Requires( il != null );
			Contract.Requires( collection != null );
			Contract.Requires( bodyEmitter != null );

			var enumerator = il.DeclareLocal( traits.GetEnumeratorMethod.ReturnType, "enumerator" );

			// gets enumerator
			if ( collection.LocalType.IsValueType )
			{
				il.EmitAnyLdloca( collection );
			}
			else
			{
				il.EmitAnyLdloc( collection );
			}

			il.EmitAnyCall( traits.GetEnumeratorMethod );
			il.EmitAnyStloc( enumerator );

			if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) )
			{
				il.BeginExceptionBlock();
			}

			var startLoop = il.DefineLabel( "START_LOOP" );
			il.MarkLabel( startLoop );
			var endLoop = il.DefineLabel( "END_LOOP" );
			var enumeratorType = traits.GetEnumeratorMethod.ReturnType;
			MethodInfo moveNextMethod = enumeratorType.GetMethod( "MoveNext", Type.EmptyTypes );
			PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty( "Current" );

			if ( moveNextMethod == null )
			{
				moveNextMethod = Metadata._IEnumerator.MoveNext;
			}

			if ( currentProperty == null )
			{
				if ( enumeratorType == typeof( IDictionaryEnumerator ) )
				{
					currentProperty = Metadata._IDictionaryEnumerator.Current;
				}
				else if ( enumeratorType.IsInterface )
				{
					if ( enumeratorType.IsGenericType && enumeratorType.GetGenericTypeDefinition() == typeof( IEnumerator<> ) )
					{
						currentProperty = typeof( IEnumerator<> ).MakeGenericType( traits.ElementType ).GetProperty( "Current" );
					}
					else
					{
						currentProperty = Metadata._IEnumerator.Current;
					}
				}
			}

			Contract.Assert( currentProperty != null, enumeratorType.ToString() );

			// iterates
			if ( traits.GetEnumeratorMethod.ReturnType.IsValueType )
			{
				il.EmitAnyLdloca( enumerator );
			}
			else
			{
				il.EmitAnyLdloc( enumerator );
			}

			il.EmitAnyCall( moveNextMethod );
			il.EmitBrfalse( endLoop );

			bodyEmitter(
				il,
				() =>
				{
					if ( traits.GetEnumeratorMethod.ReturnType.IsValueType )
					{
						il.EmitAnyLdloca( enumerator );
					}
					else
					{
						il.EmitAnyLdloc( enumerator );
					}
					il.EmitGetProperty( currentProperty );
				}
			);

			il.EmitBr( startLoop );
			il.MarkLabel( endLoop );

			// Dispose
			if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) )
			{
				il.BeginFinallyBlock();

				if ( traits.GetEnumeratorMethod.ReturnType.IsValueType )
				{
					var disposeMethod = traits.GetEnumeratorMethod.ReturnType.GetMethod( "Dispose" );
					if ( disposeMethod != null && disposeMethod.GetParameters().Length == 0 && disposeMethod.ReturnType == typeof( void ) )
					{
						il.EmitAnyLdloca( enumerator );
						il.EmitAnyCall( disposeMethod );
					}
					else
					{
						il.EmitAnyLdloc( enumerator );
						il.EmitBox( traits.GetEnumeratorMethod.ReturnType );
						il.EmitAnyCall( Metadata._IDisposable.Dispose );
					}
				}
				else
				{
					il.EmitAnyLdloc( enumerator );
					il.EmitAnyCall( Metadata._IDisposable.Dispose );
				}

				il.EndExceptionBlock();
			}
		}
		private static void CreateMapUnpackTo( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			var il = emitter.GetUnpackToMethodILGenerator();
			try
			{
				EmitInvokeMapUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdarg( 2 ) );

				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
		private static void CreatePackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			var il = emitter.GetPackToMethodILGenerator();
			try
			{
				// Array
				if ( targetType.IsArray )
				{
					/*
					 * // array
					 *  packer.PackArrayHeader( length );
					 * for( int i = 0; i < length; i++ )
					 * {
					 * 		this._serializer.PackTo( packer, collection[ i ] );
					 * }
					 */
					var length = il.DeclareLocal( typeof( int ), "length" );
					il.EmitAnyLdarg( 2 );
					il.EmitLdlen();
					il.EmitAnyStloc( length );
					il.EmitAnyLdarg( 1 );
					il.EmitAnyLdloc( length );
					il.EmitAnyCall( Metadata._Packer.PackArrayHeader );
					il.EmitPop();
					Emittion.EmitFor(
						il,
						length,
						( il0, i ) =>
						{
							Emittion.EmitSerializeValue(
								emitter,
								il0,
								1,
								traits.ElementType,
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il1.EmitAnyLdarg( 2 );
									il1.EmitAnyLdloc( i );
									il1.EmitLdelem( traits.ElementType );
								}
							);
						}
					);
				}
				else if ( traits.CountProperty == null )
				{
					/*
					 *  array = collection.ToArray();
					 *  packer.PackArrayHeader( length );
					 * for( int i = 0; i < length; i++ )
					 * {
					 * 		this._serializer.PackTo( packer, array[ i ] );
					 * }
					 */
					var array = il.DeclareLocal( traits.ElementType.MakeArrayType(), "array" );
					EmitLoadTarget( targetType, il, 2 );
					il.EmitAnyCall( Metadata._Enumerable.ToArray1Method.MakeGenericMethod( traits.ElementType ) );
					il.EmitAnyStloc( array );
					var length = il.DeclareLocal( typeof( int ), "length" );
					il.EmitAnyLdloc( array );
					il.EmitLdlen();
					il.EmitAnyStloc( length );
					il.EmitAnyLdarg( 1 );
					il.EmitAnyLdloc( length );
					il.EmitAnyCall( Metadata._Packer.PackArrayHeader );
					il.EmitPop();
					Emittion.EmitFor(
						il,
						length,
						( il0, i ) =>
						{
							Emittion.EmitSerializeValue(
								emitter,
								il0,
								1,
								traits.ElementType,
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il1.EmitAnyLdloc( array );
									il1.EmitAnyLdloc( i );
									il1.EmitLdelem( traits.ElementType );
								}
							);
						}
					);
				}
				else
				{
					/*
					 * // Enumerable
					 *  packer.PackArrayHeader( collection.Count );
					 * foreach( var item in list )
					 * {
					 * 		this._serializer.PackTo( packer, array[ i ] );
					 * }
					 */
					var collection = il.DeclareLocal( targetType, "collection" );
					// This instruction always ldarg, not to be ldarga
					il.EmitAnyLdarg( 2 );
					il.EmitAnyStloc( collection );
					var count = il.DeclareLocal( typeof( int ), "count" );
					EmitLoadTarget( targetType, il, 2 );
					il.EmitGetProperty( traits.CountProperty );
					il.EmitAnyStloc( count );
					il.EmitAnyLdarg( 1 );
					il.EmitAnyLdloc( count );
					il.EmitAnyCall( Metadata._Packer.PackArrayHeader );
					il.EmitPop();
					Emittion.EmitForEach(
						il,
						traits,
						collection,
						( il0, getCurrentEmitter ) =>
						{
							Emittion.EmitSerializeValue(
								emitter,
								il0,
								1,
								traits.ElementType,
								null,
								NilImplication.MemberDefault,
								_ => getCurrentEmitter()
							);
						}
					);
				}
				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
		private static void CreateMapUnpackFrom( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			var il = emitter.GetUnpackFromMethodILGenerator();
			try
			{
				/*
				 *	if (!unpacker.IsMapHeader)
				 *	{
				 *		throw SerializationExceptions.NewIsNotMapHeader();
				 *	}
				 *	
				 *	TDictionary<TKey, TValue> dictionary = new ...;
				 *	this.UnpackToCore(unpacker, dictionary);
				 *	return dictionary;
				 */

				if ( targetType.IsInterface || targetType.IsAbstract )
				{
					il.EmitTypeOf( targetType );
					il.EmitAnyCall( SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod );
					il.EmitThrow();
					return;
				}

				il.EmitAnyLdarg( 1 );
				il.EmitGetProperty( Metadata._Unpacker.IsMapHeader );
				var endIf = il.DefineLabel( "END_IF" );
				il.EmitBrtrue_S( endIf );
				il.EmitAnyCall( SerializationExceptions.NewIsNotMapHeaderMethod );
				il.EmitThrow();
				il.MarkLabel( endIf );

				var collection = il.DeclareLocal( targetType, "collection" );
				Emittion.EmitConstruction(
					il,
					collection,
					il0 => Emittion.EmitGetUnpackerItemsCountAsInt32( il0, 1 )
				);

				EmitInvokeMapUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdloc( collection ) );

				il.EmitAnyLdloc( collection );
				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
		private static void CreateMapUnpack( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			CreateMapUnpackFrom( targetType, emitter, traits );
			CreateMapUnpackTo( targetType, emitter, traits );
		}
		private static void CreateMapPack( Type targetType, SerializerEmitter emiter, CollectionTraits traits )
		{
			var il = emiter.GetPackToMethodILGenerator();
			try
			{

				/*
				 * 	int count = ((ICollection<KeyValuePair<string, DateTime>>)dictionary).Count;
				 * 	packer.PackMapHeader(count);
				 * 	foreach (KeyValuePair<string, DateTime> current in dictionary)
				 * 	{
				 * 		this._serializer0.PackTo(packer, current.Key);
				 * 		this._serializer1.PackTo(packer, current.Value);
				 * 	}
				 */

				var collection = il.DeclareLocal( targetType, "collection" );
				var item = il.DeclareLocal( traits.ElementType, "item" );
				var keyProperty = traits.ElementType.GetProperty( "Key" );
				var valueProperty = traits.ElementType.GetProperty( "Value" );
				// This instruction is always ldarg, not to be ldarga.
				il.EmitAnyLdarg( 2 );
				il.EmitAnyStloc( collection );
				var count = il.DeclareLocal( typeof( int ), "count" );
				EmitLoadTarget( targetType, il, collection );
				il.EmitGetProperty( traits.CountProperty );
				il.EmitAnyStloc( count );
				il.EmitAnyLdarg( 1 );
				il.EmitAnyLdloc( count );
				il.EmitAnyCall( Metadata._Packer.PackMapHeader );
				il.EmitPop();

				Emittion.EmitForEach(
					il,
					traits,
					collection,
					( il0, getCurrentEmitter ) =>
					{
						if ( traits.ElementType.IsGenericType )
						{
							Contract.Assert( traits.ElementType.GetGenericTypeDefinition() == typeof( KeyValuePair<,> ) );
							getCurrentEmitter();
							il0.EmitAnyStloc( item );
							Emittion.EmitSerializeValue(
								emiter,
								il0,
								1,
								traits.ElementType.GetGenericArguments()[ 0 ],
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il1.EmitAnyLdloca( item );
									il1.EmitGetProperty( keyProperty );
								}
							);

							Emittion.EmitSerializeValue(
								emiter,
								il0,
								1,
								traits.ElementType.GetGenericArguments()[ 1 ],
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il1.EmitAnyLdloca( item );
									il1.EmitGetProperty( valueProperty );
								}
							);
						}
						else
						{
							Contract.Assert( traits.ElementType == typeof( DictionaryEntry ) );
							getCurrentEmitter();
							il0.EmitAnyStloc( item );
							Emittion.EmitSerializeValue(
								emiter,
								il0,
								1,
								typeof( MessagePackObject ),
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il0.EmitAnyLdloca( item );
									il0.EmitGetProperty( Metadata._DictionaryEntry.Key );
									il0.EmitUnbox_Any( typeof( MessagePackObject ) );
								}
							);

							Emittion.EmitSerializeValue(
								emiter,
								il0,
								1,
								typeof( MessagePackObject ),
								null,
								NilImplication.MemberDefault,
								il1 =>
								{
									il0.EmitAnyLdloca( item );
									il0.EmitGetProperty( Metadata._DictionaryEntry.Value );
									il0.EmitUnbox_Any( typeof( MessagePackObject ) );
								}
							);
						}
					}
				);
				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
		private static void EmitInvokeArrayUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting )
		{
			il.EmitAnyLdarg( unpackerArgumentIndex );
			var serializerGetting = emitter.RegisterSerializer( traits.ElementType );

			if ( targetType.IsArray )
			{
				// Array
				/*
				 * UnpackHelpers.UnpackArrayTo( unpacker, GET_SERIALIZER, collection );
				 */
				serializerGetting( il, 0 );
				loadCollectionEmitting( il );
				il.EmitAnyCall( Metadata._UnpackHelpers.UnpackArrayTo_1.MakeGenericMethod( traits.ElementType ) );
			}
			else if ( targetType.IsGenericType )
			{
				serializerGetting( il, 0 );
				loadCollectionEmitting( il );
				if ( targetType.IsValueType )
				{
					il.EmitBox( targetType );
				}

				if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) )
				{
					// with void Add( T item )
					/*
					 * Action<T> addition = TCollection.Add
					 * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition );
					 */
					var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType;
					EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<> ).MakeGenericType( itemType ) );
					il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_1.MakeGenericMethod( itemType ) );
				}
				else
				{
					// with TDiscarded Add( T item )
					/*
					 * Func<T, TDiscarded> addition = TCollection.Add
					 * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition );
					 */
					var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType;
					var discardingType = traits.AddMethod.ReturnType;
					EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( itemType, discardingType ) );
					il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_2.MakeGenericMethod( itemType, discardingType ) );
				}
			}
			else
			{
				loadCollectionEmitting( il );
				if ( targetType.IsValueType )
				{
					il.EmitBox( targetType );
				}

				if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) )
				{
					// with void Add( object item )
					/*
					 * Action<object> addition = TCollection.Add
					 * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition );
					 */
					EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<object> ) );
					il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo );
				}
				else
				{
					// with TDiscarded Add( object item )
					/*
					 * Func<TDiscarded> addition = TCollection.Add
					 * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition );
					 */
					var discardingType = traits.AddMethod.ReturnType;
					EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( typeof( object ), discardingType ) );
					il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo_1.MakeGenericMethod( discardingType ) );
				}
			}
		}
		private static void CreateUnpackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			CreateArrayUnpackFrom( targetType, emitter, traits );
			CreateArrayUnpackTo( targetType, emitter, traits );
		}
Example #16
0
        private static bool TryCreateGenericCollectionTraits(Type source, Type type, CollectionTraitOptions options, out CollectionTraits result)
        {
            if (type == typeof(IDictionary <MessagePackObject, MessagePackObject>)
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                || type == typeof(IReadOnlyDictionary <MessagePackObject, MessagePackObject>)
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
                )
            {
                result =
                    new CollectionTraits(
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                        (source == typeof(IDictionary <MessagePackObject, MessagePackObject>) || source.Implements(typeof(IDictionary <MessagePackObject, MessagePackObject>)))
                                                ? CollectionDetailedKind.GenericDictionary
                                                : CollectionDetailedKind.GenericReadOnlyDictionary,
#else
                        CollectionDetailedKind.GenericDictionary,
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
                        typeof(KeyValuePair <MessagePackObject, MessagePackObject>),
                        GetGetEnumeratorMethodFromEnumerableType(source, typeof(IEnumerable <KeyValuePair <MessagePackObject, MessagePackObject> >), options),
                        GetAddMethod(source, typeof(MessagePackObject), typeof(MessagePackObject), options),
                        GetCountGetterMethod(source, typeof(KeyValuePair <MessagePackObject, MessagePackObject>), options)
                        );

                return(true);
            }

            if (type == typeof(IEnumerable <MessagePackObject>))
            {
                var addMethod = GetAddMethod(source, typeof(MessagePackObject), options | CollectionTraitOptions.WithAddMethod);
                if (addMethod != null)
                {
                    {
                        result =
                            new CollectionTraits(
                                (source == typeof(IList <MessagePackObject>) || source.Implements(typeof(IList <MessagePackObject>)))
                                                                ? CollectionDetailedKind.GenericList
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                                                                : (source == typeof(IReadOnlyList <MessagePackObject>) || source.Implements(typeof(IReadOnlyList <MessagePackObject>)))
                                                                ? CollectionDetailedKind.GenericReadOnlyList
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
#if !NETFX_35 && !UNITY
                                                                : (source == typeof(ISet <MessagePackObject>) || source.Implements(typeof(ISet <MessagePackObject>)))
                                                                ? CollectionDetailedKind.GenericSet
#endif // !NETFX_35 && !UNITY
                                                                : (source == typeof(ICollection <MessagePackObject>) ||
                                                                   source.Implements(typeof(ICollection <MessagePackObject>)))
                                                                ? CollectionDetailedKind.GenericCollection
#if !NETFX_35 && !UNITY && !NETFX_40 && !(SILVERLIGHT && !WINDOWS_PHONE)
                                                                : (source == typeof(IReadOnlyCollection <MessagePackObject>) || source.Implements(typeof(IReadOnlyCollection <MessagePackObject>)))
                                                                ? CollectionDetailedKind.GenericReadOnlyCollection
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
                                                                : CollectionDetailedKind.GenericEnumerable,
                                typeof(MessagePackObject),
                                GetGetEnumeratorMethodFromEnumerableType(source, typeof(IEnumerable <MessagePackObject>), options),
                                addMethod,
                                GetCountGetterMethod(source, typeof(MessagePackObject), options)
                                );

                        return(true);
                    }
                }
            }

            result = default(CollectionTraits);
            return(false);
        }
        private static bool TryCreateCollectionTraitsForHasGetEnumeratorType(
            Type source,
            MethodInfo getEnumerator,
            out CollectionTraits result
            )
        {
            if (source.Implements(typeof(IDictionary <,>)))
            {
                var ienumetaorT =
                    getEnumerator.ReturnType.GetInterfaces()
                    .FirstOrDefault(@interface =>
                                    @interface.GetIsGenericType() && @interface.GetGenericTypeDefinition() == typeof(IEnumerator <>)
                                    );
                if (ienumetaorT != null)
                {
                    var elementType = ienumetaorT.GetGenericArguments()[0];
                    {
                        result = new CollectionTraits(
                            CollectionDetailedKind.GenericDictionary,
                            GetAddMethod(source, elementType.GetGenericArguments()[0], elementType.GetGenericArguments()[1]),
                            GetCountGetterMethod(source, elementType),
                            getEnumerator,
                            elementType
                            );

                        return(true);
                    }
                }
            }

            if (source.IsAssignableTo(typeof(IDictionary)))
            {
                {
                    result = new CollectionTraits(
                        CollectionDetailedKind.NonGenericDictionary,
                        GetAddMethod(source, typeof(object), typeof(object)),
                        GetCountGetterMethod(source, typeof(object)),
                        getEnumerator,
                        typeof(DictionaryEntry)
                        );

                    return(true);
                }
            }

            // Block to limit variable scope
            {
                var ienumetaorT =
                    IsIEnumeratorT(getEnumerator.ReturnType)
                                        ? getEnumerator.ReturnType
                                        : getEnumerator.ReturnType.GetInterfaces().FirstOrDefault(IsIEnumeratorT);

                if (ienumetaorT != null)
                {
                    var elementType = ienumetaorT.GetGenericArguments()[0];
                    {
                        result = new CollectionTraits(
                            source.Implements(typeof(IList <>))
                                                        ? CollectionDetailedKind.GenericList
#if !NETFX_35 && !UNITY
                                                        : source.Implements(typeof(ISet <>))
                                                        ? CollectionDetailedKind.GenericSet
#endif // !NETFX_35 && !UNITY
                                                        : source.Implements(typeof(ICollection <>))
                                                        ? CollectionDetailedKind.GenericCollection
                                                        : CollectionDetailedKind.GenericEnumerable,
                            GetAddMethod(source, elementType),
                            GetCountGetterMethod(source, elementType),
                            getEnumerator,
                            elementType
                            );

                        return(true);
                    }
                }
            }

            result = default(CollectionTraits);
            return(false);
        }
		private static void EmitInvokeMapUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting )
		{
			il.EmitAnyLdarg( unpackerArgumentIndex );
			if ( traits.ElementType.IsGenericType )
			{
				var keyType = traits.ElementType.GetGenericArguments()[ 0 ];
				var valueType = traits.ElementType.GetGenericArguments()[ 1 ];
				var keySerializerGetting = emitter.RegisterSerializer( keyType );
				var valueSerializerGetting = emitter.RegisterSerializer( valueType );
				keySerializerGetting( il, 0 );
				valueSerializerGetting( il, 0 );
				loadCollectionEmitting( il );

				if ( targetType.IsValueType )
				{
					il.EmitBox( targetType );
				}

				il.EmitAnyCall( Metadata._UnpackHelpers.UnpackMapTo_2.MakeGenericMethod( keyType, valueType ) );
			}
			else
			{
				loadCollectionEmitting( il );

				if ( targetType.IsValueType )
				{
					il.EmitBox( targetType );
				}

				il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericMapTo );
			}
		}
 public static bool BuiltInSerializerExists(ISerializerGeneratorConfiguration configuration, Type type, CollectionTraits traits)
 {
     return(GenericSerializer.IsSupported(type, traits, configuration.PreferReflectionBasedSerializer) || SerializerRepository.InternalDefault.Contains(type));
 }
		private static bool TryCreateCollectionTraitsForIEnumerableT(
			Type source,
			GenericCollectionTypes genericTypes,
			CollectionTraitOptions options,
			MethodInfo getMethod,
			out CollectionTraits result
		)
		{
			var elementType = genericTypes.IEnumerableT.GetGenericArguments()[ 0 ];
			var addMethod = GetAddMethod( source, elementType, options );
			if ( addMethod == null && ( ( options & CollectionTraitOptions.AllowNonCollectionEnumerableTypes ) != 0 ) )
			{
				// This should be non collection object isntead of "unappendable" collection.
				result = default( CollectionTraits );
				return false;
			}

			CollectionDetailedKind kind = CollectionDetailedKind.GenericEnumerable;
			if ( genericTypes.IListT != null )
			{
				kind = CollectionDetailedKind.GenericList;
			}
#if !NETFX_35 && !UNITY
			else if ( genericTypes.ISetT != null )
			{
				kind = CollectionDetailedKind.GenericSet;
			}
#endif // !NETFX_35 && !UNITY
			else if ( genericTypes.ICollectionT != null )
			{
				kind = CollectionDetailedKind.GenericCollection;
			}
#if !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
			else if ( genericTypes.IReadOnlyListT != null )
			{
				kind = CollectionDetailedKind.GenericReadOnlyList;
			}
			else if ( genericTypes.IReadOnlyCollectionT != null )
			{
				kind = CollectionDetailedKind.GenericReadOnlyCollection;
			}
#endif // !NETFX_35 && !UNITY && !NETFX_40 && !( SILVERLIGHT && !WINDOWS_PHONE )
				
			result =
				new CollectionTraits(
					kind,
					elementType,
					getMethod ?? GetGetEnumeratorMethodFromElementType( source, elementType, options ),
					addMethod,
					GetCountGetterMethod( source, elementType, options )
				);
			return true;
		}
Example #21
0
        internal static MessagePackSerializer <T> CreateInternal <T>(SerializationContext context, PolymorphismSchema schema)
        {
#if DEBUG
            Contract.Ensures(Contract.Result <MessagePackSerializer <T> >() != null);
#endif // DEBUG

#if DEBUG && !AOT && !SILVERLIGHT && !NETSTANDARD1_1
            SerializerDebugging.TraceEmitEvent(
                "SerializationContext::CreateInternal<{0}>(@{1}, {2})",
                typeof(T),
                context.GetHashCode(),
                schema == null ? "null" : schema.DebugString
                );
#endif // DEBUG && !AOT && !SILVERLIGHT && !NETSTANDARD1_1
            Type             concreteType     = null;
            CollectionTraits collectionTraits =
#if AOT
                typeof(T).GetCollectionTraits(CollectionTraitOptions.None, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes);
#else
                typeof(T).GetCollectionTraits(CollectionTraitOptions.Full, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes);
#endif // AOT

            if (typeof(T).GetIsAbstract() || typeof(T).GetIsInterface())
            {
                // Abstract collection types will be handled correctly.
                if (collectionTraits.CollectionType != CollectionKind.NotCollection)
                {
                    concreteType = context.DefaultCollectionTypes.GetConcreteType(typeof(T));
                }

                if (concreteType == null)
                {
                    // return null for polymoirphic provider.
                    return(null);
                }

                ValidateType(concreteType);
            }
            else
            {
                ValidateType(typeof(T));
            }

#if FEATURE_EMIT
            ISerializerBuilder builder;
            switch (context.SerializerOptions.EmitterFlavor)
            {
#if !NETSTANDARD1_3
            case EmitterFlavor.CodeDomBased:
            {
#if DEBUG
                if (!SerializerDebugging.OnTheFlyCodeGenerationEnabled)
                {
                    throw new NotSupportedException(
                              String.Format(
                                  CultureInfo.CurrentCulture,
                                  "Flavor '{0:G}'({0:D}) is not supported for serializer instance creation.",
                                  context.SerializerOptions.EmitterFlavor
                                  )
                              );
                }

                builder = new CodeDomSerializerBuilder(typeof(T), collectionTraits);
                break;
#else // DEBUG
                throw new NotSupportedException();
#endif // DEBUG
            }
#endif // !NETSTANDARD1_3
            case EmitterFlavor.FieldBased:
            {
                builder = new AssemblyBuilderSerializerBuilder(typeof(T), collectionTraits);
                break;
            }

            default:                     // EmitterFlavor.ReflectionBased
            {
#endif // FEATURE_EMIT
            return
                (GenericSerializer.TryCreateAbstractCollectionSerializer(context, typeof(T), concreteType, schema) as MessagePackSerializer <T>
                 ?? CreateReflectionInternal <T>(context, concreteType ?? typeof(T), schema));

#if FEATURE_EMIT
        }
    }

    return((MessagePackSerializer <T>)builder.BuildSerializerInstance(context, concreteType, schema == null ? null : schema.FilterSelf()));
#endif // FEATURE_EMIT
        }
		public static bool BuiltInSerializerExists( ISerializerGeneratorConfiguration configuration, Type type, CollectionTraits traits )
		{
			return GenericSerializer.IsSupported( type, traits, configuration.PreferReflectionBasedSerializer ) || SerializerRepository.InternalDefault.Contains( type );
		}