Example #1
0
		/// <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
		}
Example #2
0
        public static MessagePackSerializer <T> Create <T>()
        {
#if DEBUG
            Contract.Ensures(Contract.Result <MessagePackSerializer <T> >() != null);
#endif // DEBUG

            return(Create <T>(SerializationContext.Default));
        }
Example #3
0
        /// <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."));
        }
Example #4
0
        /// <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));
        }
Example #5
0
        /// <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));
        }
Example #6
0
        public static Exception NewUnexpectedEndOfStream()
        {
#if DEBUG
            Contract.Ensures(Contract.Result <Exception>() != null);
#endif // DEBUG

            return(new SerializationException("Stream unexpectedly ends."));
        }
Example #7
0
        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."));
        }
Example #8
0
        /// <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));
        }
Example #9
0
        /// <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)));
        }
Example #11
0
        /// <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)));
        }
Example #12
0
        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)));
        }
Example #13
0
        /// <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)));
        }
Example #14
0
        /// <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)));
        }
Example #15
0
        /// <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)));
        }
Example #16
0
        /// <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)));
        }
Example #17
0
        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)));
        }
Example #18
0
        /// <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)));
        }
Example #20
0
        /// <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)));
        }
Example #21
0
        /// <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));
        }
Example #23
0
        /// <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)));
        }
Example #24
0
        /// <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 );
		}
Example #26
0
        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
        }
Example #27
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
        }
		/// <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
				}
			}
		}
Example #29
0
		/// <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
        }