/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses ext-type code mapping based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="codeTypeMapping">The code type mapping which maps between ext-type codes and .NET <see cref="Type"/>s.</param> /// <param name="keySchema">The schema for dictionary keys of the serialization target dictionary.</param> /// <param name="valueSchema">The schema for dictionary values of the serialization target dictionary.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses ext-type code mapping based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicDictionary( Type targetType, IDictionary<string, Type> codeTypeMapping, PolymorphismSchema keySchema, PolymorphismSchema valueSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.KnownTypes, codeTypeMapping, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.DictionaryKeyValues, keySchema, valueSchema ); }
/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses type embedding based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="keySchema">The schema for dictionary keys of the serialization target dictionary.</param> /// <param name="valueSchema">The schema for dictionary values of the serialization target dictionary.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses type embedding based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicDictionary( Type targetType, PolymorphismSchema keySchema, PolymorphismSchema valueSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.RuntimeType, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.DictionaryKeyValues, keySchema, valueSchema ); }
/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses type embedding based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="keySchema">The schema for dictionary keys of the serialization target dictionary.</param> /// <param name="valueSchema">The schema for dictionary values of the serialization target dictionary.</param> /// <param name="typeVerifier">The delegate which verifies loading type in runtime type polymorphism.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses type embedding based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicDictionary( Type targetType, PolymorphismSchema keySchema, PolymorphismSchema valueSchema, Func<PolymorphicTypeVerificationContext, bool> typeVerifier ) { return new PolymorphismSchema( targetType, PolymorphismType.RuntimeType, typeVerifier, PolymorphismSchemaChildrenType.DictionaryKeyValues, keySchema, valueSchema ); }
/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses ext-type code mapping based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="codeTypeMapping">The code type mapping which maps between ext-type codes and .NET <see cref="Type"/>s.</param> /// <param name="itemSchema">The schema for collection items of the serialization target collection.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses ext-type code mapping based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicCollection( Type targetType, IDictionary<string, Type> codeTypeMapping, PolymorphismSchema itemSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.KnownTypes, codeTypeMapping, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.CollectionItems, itemSchema ); }
// Dictionary key/values /// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses declared type or context specified concrete type. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="keySchema">The schema for dictionary keys of the serialization target dictionary.</param> /// <param name="valueSchema">The schema for dictionary values of the serialization target dictionary.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for dictionary object which uses declared type or context specified concrete type.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForContextSpecifiedDictionary( Type targetType, PolymorphismSchema keySchema, PolymorphismSchema valueSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.None, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.DictionaryKeyValues, keySchema, valueSchema ); }
internal ResolveSerializerEventArgs(SerializationContext context, Type targetType, PolymorphismSchema schema) { this.Context = context; this.TargetType = targetType; this.PolymorphismSchema = schema ?? PolymorphismSchema.Default; }
/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses type embedding based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="itemSchema">The schema for collection items of the serialization target collection.</param> /// <param name="typeVerifier">The delegate which verifies loading type in runtime type polymorphism.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses type embedding based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicCollection( Type targetType, PolymorphismSchema itemSchema, Func<PolymorphicTypeVerificationContext, bool> typeVerifier ) { return new PolymorphismSchema( targetType, PolymorphismType.RuntimeType, typeVerifier, PolymorphismSchemaChildrenType.CollectionItems, itemSchema ); }
// Collection items /// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses declared type or context specified concrete type. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="itemSchema">The schema for collection items of the serialization target collection.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses declared type or context specified concrete type.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForContextSpecifiedCollection(Type targetType, PolymorphismSchema itemSchema) { return (new PolymorphismSchema( targetType, PolymorphismType.None, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.CollectionItems, itemSchema )); }
// Collection items /// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses declared type or context specified concrete type. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="itemSchema">The schema for collection items of the serialization target collection.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses declared type or context specified concrete type.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForContextSpecifiedCollection( Type targetType, PolymorphismSchema itemSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.None, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.CollectionItems, itemSchema ); }
internal static MessagePackSerializer CreateInternal(SerializationContext context, Type targetType, PolymorphismSchema schema) { #if UNITY return (( Delegate.CreateDelegate( typeof(Func <SerializationContext, PolymorphismSchema, object>), CreateInternal_2.MakeGenericMethod(targetType) ) as Func <SerializationContext, PolymorphismSchema, object>)(context, schema) as MessagePackSerializer); #else return ((CreateInternal_2.MakeGenericMethod(targetType).CreateDelegate(typeof(Func <SerializationContext, PolymorphismSchema, object>)) as Func <SerializationContext, PolymorphismSchema, object>)(context, schema) as MessagePackSerializer); #endif // UNITY }
internal static MessagePackSerializer <T> CreateReflectionInternal <T>(SerializationContext context, Type concreteType, PolymorphismSchema schema) { if (concreteType.GetIsAbstract() || concreteType.GetIsInterface()) { // return null for polymoirphic provider. return(null); } var serializer = context.Serializers.Get <T>(context); if (serializer != null) { // For MessagePack.Create compatibility. // Required for built-in types. return(serializer); } ValidateType(typeof(T)); var traits = #if !UNITY typeof(T).GetCollectionTraits(CollectionTraitOptions.WithAddMethod, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes); #else typeof(T).GetCollectionTraits(CollectionTraitOptions.WithAddMethod | CollectionTraitOptions.WithCountPropertyGetter, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes); #endif switch (traits.CollectionType) { case CollectionKind.Array: case CollectionKind.Map: { return (#if !UNITY ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default))); #else Wrap <T>( context, ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default)) ); #endif // !UNITY } default: { if (typeof(T).GetIsEnum()) { return(ReflectionSerializerHelper.CreateReflectionEnumMessagePackSerializer <T>(context)); } #if !NETFX_35 && !UNITY if (TupleItems.IsTuple(typeof(T))) { return (new ReflectionTupleMessagePackSerializer <T>( context, (schema ?? PolymorphismSchema.Default).ChildSchemaList )); } #endif // !NETFX_35 && !UNITY SerializationTarget.VerifyType(typeof(T)); var target = SerializationTarget.Prepare(context, typeof(T)); return(new ReflectionObjectMessagePackSerializer <T>(context, target, target.GetCapabilitiesForObject())); } } }
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 SerializerDebugging.TraceEmitEvent( "SerializationContext::CreateInternal<{0}>(@{1}, {2})", typeof(T), context.GetHashCode(), schema == null ? "null" : schema.DebugString ); #endif // DEBUG && !AOT && !SILVERLIGHT 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) { 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 throw new NotSupportedException(); #endif } 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 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 void TracePolimorphicSchemaEvent(string format, MemberInfo memberInfo, PolymorphismSchema schema) { #if DEBUG #if FEATURE_EMIT if (!_traceEnabled) { return; } Tracer.Emit.TraceEvent(Tracer.EventType.PolimorphicSchema, Tracer.EventId.PolimorphicSchema, format, memberInfo, schema == null ? "(null)" : schema.DebugString); #endif // FEATURE_EMIT #endif }
// Tuple items /// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for <see cref="Tuple"/> object. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="itemSchemaList">The schema for collection items of the serialization target tuple. <c>null</c> or empty indicates all items do not have any polymorphism.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for <see cref="Tuple"/> object.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> /// <exception cref="System.ArgumentException">A count of <paramref name="itemSchemaList"/> does not match for an arity of the tuple type specified as <paramref name="targetType"/>.</exception> public static PolymorphismSchema ForPolymorphicTuple( Type targetType, PolymorphismSchema[] itemSchemaList ) { VerifyArity( targetType, itemSchemaList ); return new PolymorphismSchema( targetType, PolymorphismType.None, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.TupleItems, itemSchemaList ); }
/// <summary> /// Creates a new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses type embedding based polymorphism. /// </summary> /// <param name="targetType">The type of the serialization target.</param> /// <param name="itemSchema">The schema for collection items of the serialization target collection.</param> /// <returns>A new instance of the <see cref="PolymorphismSchema"/> class for collection object which uses type embedding based polymorphism.</returns> /// <exception cref="System.ArgumentNullException"><paramref name="targetType"/> is <c>null</c>.</exception> public static PolymorphismSchema ForPolymorphicCollection( Type targetType, PolymorphismSchema itemSchema ) { return new PolymorphismSchema( targetType, PolymorphismType.RuntimeType, DefaultTypeVerfiier, PolymorphismSchemaChildrenType.CollectionItems, itemSchema ); }
public MessagePackSerializer Activate( SerializationContext context, PolymorphismSchema schema ) { if ( this._constructor1 == null && this._constructor3 == null ) { throw new Exception( "A cosntructor of type '" + this._serializerType.FullName + "' is not found." ); } #if !UNITY MessagePackSerializer<T> serializer; if ( this._constructor1 != null ) { serializer = ( MessagePackSerializer<T> )this._constructor1.InvokePreservingExceptionType( context ); } else { serializer = ( MessagePackSerializer<T> )this._constructor3.InvokePreservingExceptionType( context, this._serializationTargetType, null ); } return new PolymorphicSerializerProvider<T>( serializer ).Get( context, schema ?? PolymorphismSchema.Default ) as MessagePackSerializer; #else MessagePackSerializer serializer; if ( this._constructor1 != null ) { serializer = this._constructor1.InvokePreservingExceptionType( context ) as MessagePackSerializer; } else { serializer = this._constructor3.InvokePreservingExceptionType( context, this._serializationTargetType, null ) as MessagePackSerializer; } return ReflectionExtensions.CreateInstancePreservingExceptionType<MessagePackSerializerProvider>( typeof( PolymorphicSerializerProvider<> ).MakeGenericType( this._targetType ), context, serializer ).Get( context, schema ?? PolymorphismSchema.Default ) as MessagePackSerializer; #endif // !UNITY }
public static void TracePolimorphicSchemaEvent(string format, MemberInfo memberInfo, PolymorphismSchema schema) { #if DEBUG #if !UNITY && !SILVERLIGHT && !WINDOWS_UWP if (!_traceEnabled) { return; } Tracer.Emit.TraceEvent(Tracer.EventType.PolimorphicSchema, Tracer.EventId.PolimorphicSchema, format, memberInfo, schema == null ? "(null)" : schema.DebugString); #endif // !UNITY && !SILVERLIGHT && !WINDOWS_UWP #endif }