/// <summary> /// Gets the serializer for the specified <see cref="Type"/>. /// </summary> /// <param name="targetType">Type of the serialization target.</param> /// <param name="providerParameter">A provider specific parameter. See remarks section of <see cref="GetSerializer{T}(Object)"/> for details.</param> /// <returns> /// <see cref="MessagePackSerializer"/>. /// If there is exiting one, returns it. /// Else the new instance will be created. /// If the platform supports async/await programming model, return type is <c>IAsyncMessagePackSingleObjectSerializer</c>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="targetType"/> is <c>null</c>. /// </exception> /// <remarks> /// Although <see cref="GetSerializer{T}(Object)"/> is preferred, /// this method can be used from non-generic type or methods. /// </remarks> public MessagePackSerializer GetSerializer( Type targetType, object providerParameter ) { if ( targetType == null ) { throw new ArgumentNullException( "targetType" ); } #if DEBUG Contract.Ensures( Contract.Result<MessagePackSerializer>() != null ); #endif // DEBUG #if UNITY try { #endif // UNITY return SerializerGetter.Instance.Get( this, targetType, providerParameter ); #if UNITY } catch ( Exception ex ) { AotHelper.HandleAotError( targetType, ex ); throw; } #endif // UNITY }
public static MessagePackSerializer <T> Create <T>() { #if DEBUG Contract.Ensures(Contract.Result <MessagePackSerializer <T> >() != null); #endif // DEBUG return(Create <T>(SerializationContext.Default)); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the unpacking collection is too large to represents in the current runtime environment. /// </summary> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewIsTooLargeCollection() { #if DEBUG Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new MessageNotSupportedException("The collection which has more than Int32.MaxValue items is not supported.")); }
/// <summary> /// Creates new <see cref="SerializerEmitter"/> which corresponds to the specified <see cref="EmitterFlavor"/>. /// </summary> /// <param name="context">The <see cref="SerializationContext"/>.</param> /// <param name="specification">The specification of the serializer.</param> /// <returns>New <see cref="SerializerEmitter"/> which corresponds to the specified <see cref="EmitterFlavor"/>.</returns> public SerializerEmitter CreateEnumEmitter(SerializationContext context, SerializerSpecification specification) { Contract.Requires(context != null); Contract.Requires(specification != null); Contract.Ensures(Contract.Result <SerializerEmitter>() != null); return(new SerializerEmitter(context, this._module, specification, this._isDebuggable)); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the underlying stream is not correct semantically because failed to unpack items count of array/map. /// </summary> /// <param name="innerException">The inner exception for the debug. The value is implementation specific.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewIsIncorrectStream(Exception innerException) { #if DEBUG Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException("Failed to unpack items count of the collection.", innerException)); }
public static Exception NewUnexpectedEndOfStream() { #if DEBUG Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException("Stream unexpectedly ends.")); }
public static Exception NewIsNotMapHeader() { #if DEBUG Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException("Unpacker is not in the map header. The stream may not be map.")); }
/// <summary> /// Creates new <see cref="SerializerEmitter"/> which corresponds to the specified <see cref="EmitterFlavor"/>. /// </summary> /// <param name="specification">The specification of the serializer.</param> /// <param name="baseClass">Type of the base class of the serializer.</param> /// <returns>New <see cref="SerializerEmitter"/> which corresponds to the specified <see cref="EmitterFlavor"/>.</returns> public SerializerEmitter CreateObjectEmitter(SerializerSpecification specification, Type baseClass) { Contract.Requires(specification != null); Contract.Requires(baseClass != null); Contract.Ensures(Contract.Result <SerializerEmitter>() != null); return(new SerializerEmitter(this._module, specification, baseClass, this._isDebuggable)); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the unpacking collection value is not a collection. /// </summary> /// <param name="memberName">The name of the member.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewStreamDoesNotContainCollectionForMember(string memberName) { #if DEBUG Contract.Requires(!String.IsNullOrEmpty(memberName)); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot deserialize member '{0}' because the underlying stream does not contain collection.", memberName))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that target type is not serializable because it does not have public default constructor. /// </summary> /// <param name="type">The target type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> internal static Exception NewTargetDoesNotHavePublicDefaultConstructor(Type type) { #if !UNITY Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // !UNITY return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Type '{0}' does not have default (parameterless) public constructor.", type))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the member cannot be <c>null</c> or the unpacking value cannot be nil because nil value is explicitly prohibitted. /// </summary> /// <param name="memberName">The name of the member.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewNullIsProhibited(string memberName) { #if DEBUG Contract.Requires(!String.IsNullOrEmpty(memberName)); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "The member '{0}' cannot be nil.", memberName))); }
public static Exception NewMissingItem(int index) // For compatibility only. { #if DEBUG Contract.Requires(index >= 0); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new InvalidMessagePackStreamException(String.Format(CultureInfo.CurrentCulture, "Items at index '{0}' is missing.", index))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that value type cannot be <c>null</c> on deserialization. /// </summary> /// <param name="type">The target type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewValueTypeCannotBeNull(Type type) { #if DEBUG Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot be null '{0}' type value.", type))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that target collection type does not declare appropriate Add(T) method. /// </summary> /// <param name="type">The target type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewMissingAddMethod(Type type) { #if DEBUG Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Type '{0}' does not have appropriate Add method.", type))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that required field is not found on the unpacking stream. /// </summary> /// <param name="name">The name of the property.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewMissingProperty(string name) { #if DEBUG Contract.Requires(!String.IsNullOrEmpty(name)); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Property '{0}' is missing.", name))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that target type is not serializable because it does not have both of public default constructor and public constructor with an Int32 parameter. /// </summary> /// <param name="type">The target type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> internal static Exception NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(Type type) { #if DEBUG Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Type '{0}' does not have both of default (parameterless) public constructor and public constructor with an Int32 parameter.", type))); }
public static Exception NewTupleCardinarityIsNotMatch(int expectedTupleCardinality, int actualArrayLength) { #if DEBUG Contract.Requires(expectedTupleCardinality > 0); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "The length of array ({0}) does not match to tuple cardinality ({1}).", actualArrayLength, expectedTupleCardinality))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that operation is not supported because <paramref name="type"/> cannot be instanciated. /// </summary> /// <param name="type">Type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewNotSupportedBecauseCannotInstanciateAbstractType(Type type) { #if DEBUG Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new NotSupportedException(String.Format(CultureInfo.CurrentCulture, "This operation is not supported because '{0}' cannot be instanciated.", type))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that value type cannot serialize. /// </summary> /// <param name="type">The target type.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewTypeCannotSerialize(Type type) { #if !UNITY Contract.Requires(type != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // !UNITY return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot serialize '{0}' type.", type))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the unpacking value cannot be nil because the target member is read only and its type is collection. /// </summary> /// <param name="memberName">The name of the member.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewReadOnlyMemberItemsMustNotBeNull(string memberName) { #if DEBUG Contract.Requires(!String.IsNullOrEmpty(memberName)); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "The member '{0}' cannot be nil because it is read only member.", memberName))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that the unpacking array size is not expected length. /// </summary> /// <param name="expectedLength">Expected, required for deserialization array length.</param> /// <param name="actualLength">Actual array length.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewUnexpectedArrayLength(int expectedLength, int actualLength) { #if DEBUG Contract.Requires(expectedLength >= 0); Contract.Requires(actualLength >= 0); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "The MessagePack stream is invalid. Expected array length is {0}, but actual is {1}.", expectedLength, actualLength))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that value type cannot deserialize. /// </summary> /// <param name="type">The target type.</param> /// <param name="memberName">The name of deserializing member.</param> /// <param name="inner">The inner exception.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewTypeCannotDeserialize(Type type, string memberName, Exception inner) { #if !UNITY Contract.Requires(type != null); Contract.Requires(!String.IsNullOrEmpty(memberName)); Contract.Requires(inner != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // !UNITY return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot deserialize member '{1}' of type '{0}'.", type, memberName), inner)); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that value type cannot be <c>null</c> on deserialization. /// </summary> /// <param name="name">The name of the member.</param> /// <param name="memberType">The type of the member.</param> /// <param name="declaringType">The type that declares the member.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewValueTypeCannotBeNull(string name, Type memberType, Type declaringType) { #if DEBUG Contract.Requires(!String.IsNullOrEmpty(name)); Contract.Requires(memberType != null); Contract.Requires(declaringType != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Member '{0}' of type '{1}' cannot be null because it is value type('{2}').", name, declaringType, memberType))); }
/// <summary> /// <strong>This is intended to MsgPack for CLI internal use. Do not use this type from application directly.</strong> /// Returns new exception to notify that it is failed to deserialize member. /// </summary> /// <param name="targetType">Deserializing type.</param> /// <param name="memberName">The name of the deserializing member.</param> /// <param name="inner">The exception which caused current error.</param> /// <returns><see cref="Exception"/> instance. It will not be <c>null</c>.</returns> public static Exception NewFailedToDeserializeMember(Type targetType, string memberName, Exception inner) { #if DEBUG Contract.Requires(targetType != null); Contract.Requires(!String.IsNullOrEmpty(memberName)); Contract.Requires(inner != null); Contract.Ensures(Contract.Result <Exception>() != null); #endif // DEBUG return(new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot deserialize member '{0}' of type '{1}'.", memberName, targetType), inner)); }
/// <summary> /// Gets the serializer for the specified <see cref="Type"/>. /// </summary> /// <param name="targetType">Type of the serialization target.</param> /// <param name="providerParameter">A provider specific parameter. See remarks section of <see cref="GetSerializer{T}(Object)"/> for details.</param> /// <returns> /// <see cref="IMessagePackSingleObjectSerializer"/>. /// If there is exiting one, returns it. /// Else the new instance will be created. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="targetType"/> is <c>null</c>. /// </exception> /// <remarks> /// Although <see cref="GetSerializer{T}(Object)"/> is preferred, /// this method can be used from non-generic type or methods. /// </remarks> public IMessagePackSingleObjectSerializer GetSerializer( Type targetType, object providerParameter ) { if ( targetType == null ) { throw new ArgumentNullException( "targetType" ); } #if !UNITY Contract.Ensures( Contract.Result<IMessagePackSerializer>() != null ); #endif // !UNITY return SerializerGetter.Instance.Get( this, targetType, providerParameter ); }
public static MessagePackSerializer Create(Type targetType, SerializationContext context) { if (targetType == null) { throw new ArgumentNullException("targetType"); } if (context == null) { throw new ArgumentNullException("context"); } #if DEBUG Contract.Ensures(Contract.Result <MessagePackSerializer>() != null); #endif // DEBUG #if AOT return(CreateInternal(context, targetType, null)); #else // MPS.Create should always return new instance, and creator delegate should be cached for performance. #if NETSTANDARD1_1 || NETSTANDARD1_3 var factory = _creatorCache.GetOrAdd( targetType, type => // Utilize covariance of delegate. Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(type).CreateDelegate( typeof(Func <SerializationContext, MessagePackSerializer>) ) as Func <SerializationContext, MessagePackSerializer> ); #elif SILVERLIGHT || NET35 Func <SerializationContext, MessagePackSerializer> factory; lock ( _syncRoot ) { _creatorCache.TryGetValue(targetType, out factory); } if (factory == null) { // Utilize covariance of delegate. factory = Delegate.CreateDelegate( typeof(Func <SerializationContext, MessagePackSerializer>), Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(targetType) ) as Func <SerializationContext, MessagePackSerializer>; Contract.Assert(factory != null); lock ( _syncRoot ) { _creatorCache[targetType] = factory; } } #else var factory = _creatorCache.GetOrAdd( targetType, type => // Utilize covariance of delegate. Delegate.CreateDelegate( typeof(Func <SerializationContext, MessagePackSerializer>), Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(type) ) as Func <SerializationContext, MessagePackSerializer> ); #endif // NETSTANDARD1_1 || NETSTANDARD1_3 return(factory(context)); #endif // AOT }
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 }
/// <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 } } }
/// <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 } } } }
public static IMessagePackSingleObjectSerializer Create(Type targetType, SerializationContext context) { if (targetType == null) { throw new ArgumentNullException("targetType"); } if (context == null) { throw new ArgumentNullException("context"); } #if !UNITY Contract.Ensures(Contract.Result <IMessagePackSerializer>() != null); #endif // !UNITY #if XAMIOS || XAMDROID || UNITY return(CreateInternal(context, targetType, null)); #else // MPS.Create should always return new instance, and creator delegate should be cached for performance. #if NETFX_CORE var factory = _creatorCache.GetOrAdd( targetType, type => { var contextParameter = Expression.Parameter(typeof(SerializationContext), "context"); // Utilize covariance of delegate. return (Expression.Lambda <Func <SerializationContext, IMessagePackSingleObjectSerializer> >( Expression.Call( null, Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(type), contextParameter ), contextParameter ).Compile()); } ); #elif SILVERLIGHT || NETFX_35 Func <SerializationContext, IMessagePackSingleObjectSerializer> factory; lock ( _syncRoot ) { _creatorCache.TryGetValue(targetType, out factory); } if (factory == null) { // Utilize covariance of delegate. factory = Delegate.CreateDelegate( typeof(Func <SerializationContext, IMessagePackSingleObjectSerializer>), Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(targetType) ) as Func <SerializationContext, IMessagePackSingleObjectSerializer>; Contract.Assert(factory != null); lock ( _syncRoot ) { _creatorCache[targetType] = factory; } } #else var factory = _creatorCache.GetOrAdd( targetType, type => // Utilize covariance of delegate. Delegate.CreateDelegate( typeof(Func <SerializationContext, IMessagePackSingleObjectSerializer>), Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod(type) ) as Func <SerializationContext, IMessagePackSingleObjectSerializer> ); #endif // NETFX_CORE return(factory(context)); #endif // XAMIOS || XAMDROID || UNITY else }