public SerializerCapabilities GetCapabilitiesForCollection(CollectionTraits traits) { return (!this.CanDeserialize ? SerializerCapabilities.PackTo : traits.AddMethod == null ? (SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom) : (SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom | SerializerCapabilities.UnpackTo)); }
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); }
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)); }
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; }
/// <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 ); }
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; }
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 ); }