internal SerializationContext(SerializerRepository serializers) { this._emitterFlavor = MsgPack.Serialization.EmitterFlavor.FieldBased; Contract.Requires(serializers != null); this._compatibilityOptions = new SerializationCompatibilityOptions(); this._serializers = serializers; this._typeLock = new HashSet <Type>(); }
public SerializerRepository(SerializerRepository copiedFrom) { if (copiedFrom == null) { throw new ArgumentNullException("copiedFrom"); } this._repository = new TypeKeyRepository(copiedFrom._repository); }
internal SerializationContext(SerializerRepository serializers) { Contract.Requires(serializers != null); this._compatibilityOptions = new SerializationCompatibilityOptions(); this._serializers = serializers; #if SILVERLIGHT || NETFX_35 this._typeLock = new HashSet <Type>(); #else this._typeLock = new ConcurrentDictionary <Type, object>(); #endif }
internal SerializationContext( SerializerRepository serializers, PackerCompatibilityOptions packerCompatibilityOptions) { Contract.Requires(serializers != null); this._compatibilityOptions = new SerializationCompatibilityOptions() { PackerCompatibilityOptions = packerCompatibilityOptions }; this._serializers = serializers; this._typeLock = new HashSet <Type>(); this._defaultCollectionTypes = new DefaultConcreteTypeRepository(); }
internal SerializationContext( SerializerRepository serializers, PackerCompatibilityOptions packerCompatibilityOptions) { Contract.Requires(serializers != null); this._compatibilityOptions = new SerializationCompatibilityOptions() { PackerCompatibilityOptions = packerCompatibilityOptions }; this._serializers = serializers; #if SILVERLIGHT || NETFX_35 this._typeLock = new HashSet <Type>(); #else this._typeLock = new ConcurrentDictionary <Type, object>(); #endif this._defaultCollectionTypes = new DefaultConcreteTypeRepository(); }
internal SerializationContext( SerializerRepository serializers, PackerCompatibilityOptions packerCompatibilityOptions) { this._compatibilityOptions = new SerializationCompatibilityOptions { PackerCompatibilityOptions = packerCompatibilityOptions }; this._serializers = serializers; #if !XAMIOS && !XAMDROID && !UNITY #if SILVERLIGHT || NETFX_35 this._typeLock = new Dictionary <Type, object>(); #else this._typeLock = new ConcurrentDictionary <Type, object>(); #endif // SILVERLIGHT || NETFX_35 #endif // !XAMIOS && !XAMDROID && !UNITY this._defaultCollectionTypes = new DefaultConcreteTypeRepository(); }
/// <summary> /// Initializes a new instance of the <see cref="SerializationContext"/> class with copy of <see cref="SerializerRepository.GetDefault()"/> for specified <see cref="PackerCompatibilityOptions"/>. /// </summary> /// <param name="packerCompatibilityOptions"><see cref="PackerCompatibilityOptions"/> which will be used on built-in serializers.</param> public SerializationContext( PackerCompatibilityOptions packerCompatibilityOptions ) { this._compatibilityOptions = new SerializationCompatibilityOptions { PackerCompatibilityOptions = packerCompatibilityOptions }; this._serializers = new SerializerRepository( SerializerRepository.GetDefault( this ) ); #if SILVERLIGHT || NETFX_35 || UNITY this._typeLock = new Dictionary<Type, object>(); #else this._typeLock = new ConcurrentDictionary<Type, object>(); #endif // SILVERLIGHT || NETFX_35 || UNITY this._generationLock = new object(); this._defaultCollectionTypes = new DefaultConcreteTypeRepository(); this._serializerGeneratorOptions = new SerializerOptions(); }
/// <summary> /// Initializes a new instance of the <see cref="SerializationContext"/> class with copy of <see cref="SerializerRepository.GetDefault()"/> for specified <see cref="PackerCompatibilityOptions"/>. /// </summary> /// <param name="packerCompatibilityOptions"><see cref="PackerCompatibilityOptions"/> which will be used on built-in serializers.</param> public SerializationContext( PackerCompatibilityOptions packerCompatibilityOptions ) { this._compatibilityOptions = new SerializationCompatibilityOptions { PackerCompatibilityOptions = packerCompatibilityOptions }; this._serializers = new SerializerRepository( SerializerRepository.GetDefault( this ) ); #if !FEATURE_CONCURRENT this._typeLock = new Dictionary<Type, object>(); #else this._typeLock = new ConcurrentDictionary<Type, object>(); #endif // !FEATURE_CONCURRENT this._generationLock = new object(); this._defaultCollectionTypes = new DefaultConcreteTypeRepository(); this._serializerGeneratorOptions = new SerializerOptions(); this._dictionarySerializationOptions = new DictionarySerlaizationOptions(); this._enumSerializationOptions = new EnumSerializationOptions(); }
/// <summary> /// Gets the <see cref="MessagePackSerializer{T}"/> with this instance. /// </summary> /// <typeparam name="T">Type of serialization/deserialization target.</typeparam> /// <param name="providerParameter">A provider specific parameter. See remarks section for details.</param> /// <returns> /// <see cref="MessagePackSerializer{T}"/>. /// If there is exiting one, returns it. /// Else the new instance will be created. /// </returns> /// <remarks> /// <para> /// This method automatically register new instance via <see cref="SerializerRepository.Register{T}(MessagePackSerializer{T})"/>. /// </para> /// <para> /// Currently, only following provider parameters are supported. /// <list type="table"> /// <listheader> /// <term>Target type</term> /// <description>Provider parameter</description> /// </listheader> /// <item> /// <term><see cref="EnumMessagePackSerializer{TEnum}"/> or its descendants.</term> /// <description><see cref="EnumSerializationMethod"/>. The returning instance corresponds to this value for serialization.</description> /// </item> /// </list> /// <note><c>null</c> is valid value for <paramref name="providerParameter"/> and it indeicates default behavior of parameter.</note> /// </para> /// </remarks> public MessagePackSerializer<T> GetSerializer<T>( object providerParameter ) { #if !UNITY Contract.Ensures( Contract.Result<MessagePackSerializer<T>>() != null ); #endif // !UNITY var schema = providerParameter as PolymorphismSchema; // Explicitly generated serializer should always used, so get it first. MessagePackSerializer<T> serializer = this._serializers.Get<T>( this, providerParameter ); if ( serializer != null ) { return serializer; } object aquiredLock = null; bool lockTaken = false; try { try { } finally { var newLock = new object(); #if SILVERLIGHT || NETFX_35 || UNITY Monitor.Enter( newLock ); try { lock ( this._typeLock ) { lockTaken = !this._typeLock.TryGetValue( typeof( T ), out aquiredLock ); if ( lockTaken ) { aquiredLock = newLock; this._typeLock.Add( typeof( T ), newLock ); } } #else bool newLockTaken = false; try { Monitor.Enter( newLock, ref newLockTaken ); aquiredLock = this._typeLock.GetOrAdd( typeof( T ), _ => newLock ); lockTaken = newLock == aquiredLock; #endif // if SILVERLIGHT || NETFX_35 || UNITY } finally { #if SILVERLIGHT || NETFX_35 || UNITY if ( !lockTaken ) #else if ( !lockTaken && newLockTaken ) #endif // if SILVERLIGHT || NETFX_35 || UNITY { // Release the lock which failed to become 'primary' lock. Monitor.Exit( newLock ); } } } if ( Monitor.TryEnter( aquiredLock ) ) { // Decrement monitor counter. Monitor.Exit( aquiredLock ); #if DEBUG && !NETFX_40 && !NETFX_35 && !SILVERLIGHT && !UNITY Contract.Assert( Monitor.IsEntered( aquiredLock ), "Monitor.IsEntered(aquiredLock)" ); #endif // DEBUG && !NETFX_40 && !NETFX_35 !SILVERLIGHT && && !UNITY if ( lockTaken ) { // First try to create generic serializer w/o code generation. serializer = GenericSerializer.Create<T>( this, schema ); if ( serializer == null ) { #if !XAMIOS && !XAMDROID && !UNITY if ( this.IsRuntimeGenerationDisabled ) { #endif // !XAMIOS && !XAMDROID && !UNITY // On debugging, or AOT only envs, use reflection based aproach. serializer = this.GetSerializerWithoutGeneration<T>( schema ) ?? this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateReflectionInternal<T>( this, this.EnsureConcreteTypeRegistered( typeof( T ) ), schema ); #if !XAMIOS && !XAMDROID && !UNITY } else { // This thread creating new type serializer. serializer = this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateInternal<T>( this, schema ); } #endif // !XAMIOS && !XAMDROID && !UNITY } } else { // This thread owns existing lock -- thus, constructing self-composite type. // Prevent release owned lock. aquiredLock = null; return new LazyDelegatingMessagePackSerializer<T>( this, providerParameter ); } // Some types always have to use provider. MessagePackSerializerProvider provider; var asEnumSerializer = serializer as ICustomizableEnumSerializer; if ( asEnumSerializer != null ) { #if DEBUG && !UNITY Contract.Assert( typeof( T ).GetIsEnum(), typeof( T ) + " is not enum but generated serializer is ICustomizableEnumSerializer" ); #endif // DEBUG && !UNITY provider = new EnumMessagePackSerializerProvider( typeof( T ), asEnumSerializer ); } else { #if DEBUG && !UNITY Contract.Assert( !typeof( T ).GetIsEnum(), typeof( T ) + " is enum but generated serializer is not ICustomizableEnumSerializer : " + ( serializer == null ? "null" : serializer.GetType().FullName ) ); #endif // DEBUG && !UNITY // Creates provider even if no schema -- the schema might be specified future for the type. // It is OK to use polymorphic provider for value type. #if !UNITY provider = new PolymorphicSerializerProvider<T>( serializer ); #else provider = new PolymorphicSerializerProvider<T>( this, serializer ); #endif // !UNITY } #if !UNITY Type nullableType; MessagePackSerializerProvider nullableSerializerProvider; SerializerRepository.GetNullableCompanion( typeof( T ), this, serializer, out nullableType, out nullableSerializerProvider ); this._serializers.Register( typeof( T ), provider, nullableType, nullableSerializerProvider, SerializerRegistrationOptions.WithNullable ); #else this._serializers.Register( typeof( T ), provider, null, null, SerializerRegistrationOptions.None ); #endif // !UNITY } else { // Wait creation by other thread. // Acquire as 'waiting' lock. Monitor.Enter( aquiredLock ); } // Re-get to avoid duplicated registration and handle provider parameter or get the one created by prececing thread. // If T is null and schema is not provided or default schema is provided, then exception will be thrown here from the new provider. return this._serializers.Get<T>( this, providerParameter ); } finally { if ( lockTaken ) { #if SILVERLIGHT || NETFX_35 || UNITY lock ( this._typeLock ) { this._typeLock.Remove( typeof( T ) ); } #else object dummy; this._typeLock.TryRemove( typeof( T ), out dummy ); #endif // if SILVERLIGHT || NETFX_35 || UNITY } if ( aquiredLock != null ) { // Release primary lock or waiting lock. Monitor.Exit( aquiredLock ); #if DEBUG && !NETFX_40 && !NETFX_35 && !SILVERLIGHT && !UNITY Contract.Assert( !Monitor.IsEntered( aquiredLock ), "!Monitor.IsEntered(aquiredLock)" ); #endif // DEBUG && !NETFX_40 && !NETFX_35 && !SILVERLIGHT && !UNITY } } }
public void TestDefaultTableCapacity() { var table = SerializerRepository.InitializeDefaultTable(new SerializationContext()); Assert.That(table.Count, Is.LessThanOrEqualTo(SerializerRepository.DefaultTableCapacity)); }
/// <summary> /// Gets the <see cref="MessagePackSerializer{T}"/> with this instance. /// </summary> /// <typeparam name="T">Type of serialization/deserialization target.</typeparam> /// <param name="providerParameter">A provider specific parameter. See remarks section for details.</param> /// <returns> /// <see cref="MessagePackSerializer{T}"/>. /// If there is exiting one, returns it. /// Else the new instance will be created. /// </returns> /// <remarks> /// <para> /// This method automatically register new instance via <see cref="SerializerRepository.Register{T}(MessagePackSerializer{T})"/>. /// </para> /// <para> /// Currently, only following provider parameters are supported. /// <list type="table"> /// <listheader> /// <term>Target type</term> /// <description>Provider parameter</description> /// </listheader> /// <item> /// <term><see cref="EnumMessagePackSerializer{TEnum}"/> or its descendants.</term> /// <description><see cref="EnumSerializationMethod"/>. The returning instance corresponds to this value for serialization.</description> /// </item> /// </list> /// <note><c>null</c> is valid value for <paramref name="providerParameter"/> and it indeicates default behavior of parameter.</note> /// </para> /// </remarks> public MessagePackSerializer<T> GetSerializer<T>( object providerParameter ) { #if DEBUG Contract.Ensures( Contract.Result<MessagePackSerializer<T>>() != null ); #endif // DEBUG // Explicitly generated serializer should always used, so get it first. MessagePackSerializer<T> serializer = this._serializers.Get<T>( this, providerParameter ); if ( serializer != null ) { return serializer; } bool lockTaken = false; lock ( this._generationLock ) { // Re-get to check because other thread might create the serializer when I wait the lock. serializer = this._serializers.Get<T>( this, providerParameter ); if ( serializer != null ) { return serializer; } try { try { } finally { #if !FEATURE_CONCURRENT lock ( this._typeLock ) { var typeLock = new object(); object aquiredLock; lockTaken = !this._typeLock.TryGetValue( typeof( T ), out aquiredLock ); if ( lockTaken ) { this._typeLock.Add( typeof( T ), typeLock ); } } #else var typeLock = new object(); var aquiredTypeLock = this._typeLock.GetOrAdd( typeof( T ), _ => typeLock ); lockTaken = typeLock == aquiredTypeLock; #endif // !FEATURE_CONCURRENT } if ( lockTaken ) { // First try to create generic serializer w/o code generation. var schema = ( providerParameter ?? PolymorphismSchema.Create( typeof( T ), null ) ) as PolymorphismSchema; serializer = GenericSerializer.Create<T>( this, schema ); if ( serializer == null ) { #if !UNITY if ( !this._serializerGeneratorOptions.CanRuntimeCodeGeneration ) { #endif // !UNITY // On debugging, or AOT only envs, use reflection based aproach. serializer = this.GetSerializerWithoutGeneration<T>( schema ) ?? this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateReflectionInternal<T>( this, this.EnsureConcreteTypeRegistered( typeof( T ) ), schema ); #if !UNITY } else { // This thread creating new type serializer. serializer = this.OnResolveSerializer<T>( schema ) ?? MessagePackSerializer.CreateInternal<T>( this, schema ); } #endif // !UNITY } } else { // This thread owns existing lock -- thus, constructing self-composite type. return new LazyDelegatingMessagePackSerializer<T>( this, providerParameter ); } // Some types always have to use provider. MessagePackSerializerProvider provider; var asEnumSerializer = serializer as ICustomizableEnumSerializer; if ( asEnumSerializer != null ) { #if DEBUG Contract.Assert( typeof( T ).GetIsEnum(), typeof( T ) + " is not enum but generated serializer is ICustomizableEnumSerializer" ); #endif // DEBUG provider = new EnumMessagePackSerializerProvider( typeof( T ), asEnumSerializer ); } else { #if DEBUG Contract.Assert( !typeof( T ).GetIsEnum(), typeof( T ) + " is enum but generated serializer is not ICustomizableEnumSerializer : " + ( serializer == null ? "null" : serializer.GetType().FullName ) ); #endif // DEBUG // Creates provider even if no schema -- the schema might be specified future for the type. // It is OK to use polymorphic provider for value type. #if !UNITY provider = new PolymorphicSerializerProvider<T>( serializer ); #else provider = new PolymorphicSerializerProvider<T>( this, serializer ); #endif // !UNITY } #if !UNITY Type nullableType; MessagePackSerializerProvider nullableSerializerProvider; SerializerRepository.GetNullableCompanion( typeof( T ), this, serializer, out nullableType, out nullableSerializerProvider ); this._serializers.Register( typeof( T ), provider, nullableType, nullableSerializerProvider, SerializerRegistrationOptions.WithNullable ); #else this._serializers.Register( typeof( T ), provider, null, null, SerializerRegistrationOptions.None ); #endif // !UNITY // Re-get to avoid duplicated registration and handle provider parameter or get the one created by prececing thread. // If T is null and schema is not provided or default schema is provided, then exception will be thrown here from the new provider. return this._serializers.Get<T>( this, providerParameter ); } finally { if ( lockTaken ) { #if !FEATURE_CONCURRENT lock ( this._typeLock ) { this._typeLock.Remove( typeof( T ) ); } #else object dummy; this._typeLock.TryRemove( typeof( T ), out dummy ); #endif // !FEATURE_CONCURRENT } } } }
/// <summary> /// Initializes a new instance of the <see cref="SerializationContext"/> class with copy of <see cref="SerializerRepository.GetDefault(PackerCompatibilityOptions)"/> for specified <see cref="PackerCompatibilityOptions"/>. /// </summary> /// <param name="packerCompatibilityOptions"><see cref="PackerCompatibilityOptions"/> which will be used on built-in serializers.</param> public SerializationContext(PackerCompatibilityOptions packerCompatibilityOptions) : this(new SerializerRepository(SerializerRepository.GetDefault(packerCompatibilityOptions)), packerCompatibilityOptions) { }
// For default init. private SerializationContext(SerializerRepository allwaysNull) : this(allwaysNull, PackerCompatibilityOptions.Classic) // TODO: configurable { this._serializers = new SerializerRepository(SerializerRepository.GetDefault(this)); }