public override object Get(SerializationContext context, object providerParameter) { var schema = (providerParameter ?? this._defaultSchema) as PolymorphismSchema; if (schema == null || schema.UseDefault || schema.TargetType != typeof(T)) { // No schema is applied or this provider is used for container but the schema is only applied for keys/items. if (this._defaultSerializer == null) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(T)); } // Fallback. return(this._defaultSerializer); } if (schema.UseTypeEmbedding) { return(new TypeEmbedingPolymorphicMessagePackSerializer <T>(context, schema)); } else { return(new KnownTypePolymorphicMessagePackSerializer <T>(context, schema)); } }
public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter) { Contract.Requires(il != null); Contract.Requires(target != null); // TODO: For collection, supports .ctor(IEnumerable<> other) if (target.LocalType.IsAbstract || target.LocalType.IsInterface) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(target.LocalType); } if (target.LocalType.IsArray) { Contract.Assert(initialCountLoadingEmitter != null); initialCountLoadingEmitter(il); il.EmitNewarr(target.LocalType.GetElementType()); il.EmitAnyStloc(target); return; } ConstructorInfo ctor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes); if (ctor != null && initialCountLoadingEmitter != null && typeof(IEnumerable).IsAssignableFrom(target.LocalType)) { if (target.LocalType.IsValueType) { // Same as general method call var capacity = il.DeclareLocal(typeof(int), "capacity"); initialCountLoadingEmitter(il); il.EmitAnyStloc(capacity); il.EmitAnyLdloca(target); il.EmitAnyLdloc(capacity); il.EmitCallConstructor(ctor); } else { initialCountLoadingEmitter(il); il.EmitNewobj(ctor); il.EmitAnyStloc(target); } return; } if (target.LocalType.IsValueType) { // ValueType instance has been initialized by the runtime. return; } ctor = target.LocalType.GetConstructor(Type.EmptyTypes); if (ctor == null) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType); } il.EmitNewobj(ctor); il.EmitAnyStloc(target); }
public ListExpressionMessagePackSerializer(SerializationContext context, CollectionTraits traits) : base(context, traits) { Type type = typeof(T); if (type.GetIsAbstract()) { type = context.DefaultCollectionTypes.GetConcreteType(typeof(T)) ?? type; } if (type.IsArray) { var capacityParameter = Expression.Parameter(typeof(int), "length"); this._createInstanceWithCapacity = Expression.Lambda <Func <int, T> >( Expression.NewArrayBounds(type.GetElementType(), capacityParameter), capacityParameter ).Compile(); this._createInstance = null; } else if (type.GetIsAbstract()) { this._createInstance = () => { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); }; this._createInstanceWithCapacity = null; } else { var constructor = ExpressionSerializerLogics.GetCollectionConstructor(context, type); if (constructor == null) { this._createInstance = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(type); }; this._createInstanceWithCapacity = null; } else { if (constructor.GetParameters().Length == 1) { this._createInstance = null; var capacityParameter = Expression.Parameter(typeof(int), "parameter"); this._createInstanceWithCapacity = Expression.Lambda <Func <int, T> >( Expression.New(constructor, capacityParameter), capacityParameter ).Compile(); } else { this._createInstanceWithCapacity = null; this._createInstance = Expression.Lambda <Func <T> >( Expression.New(constructor) ).Compile(); } } } }
public ListReflectionMessagePackSerializer(Type type, SerializationContext context, CollectionTraits traits) : base(type, context, traits) { if (type.GetIsAbstract()) { type = context.DefaultCollectionTypes.GetConcreteType(type) ?? type; } if (type.IsArray) { var elementType = type.GetElementType(); this._createInstanceWithCapacity = length => { return(Array.CreateInstance(elementType, length)); }; this._createInstance = null; } else if (type.GetIsAbstract()) { this._createInstance = () => { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); }; this._createInstanceWithCapacity = null; } else { var constructor = ReflectionSerializerLogics.GetCollectionConstructor(context, type); if (constructor == null) { this._createInstance = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(type); }; this._createInstanceWithCapacity = null; } else { if (constructor.GetParameters().Length == 1) { this._createInstance = null; this._createInstanceWithCapacity = length => constructor.Invoke(new object[] { length }); } else { this._createInstanceWithCapacity = null; this._createInstance = () => constructor.Invoke(new object[0]); } } } }
public static void GetConcreteSerializer( SerializationContext context, PolymorphismSchema schema, Type abstractType, Type targetType, Type exampleType, out ICollectionInstanceFactory factory, out IMessagePackSingleObjectSerializer serializer ) { if (abstractType == targetType) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(abstractType); } serializer = context.GetSerializer(targetType, schema); factory = serializer as ICollectionInstanceFactory; if (factory == null && (serializer as IPolymorphicDeserializer) == null) { throw SerializationExceptions.NewIncompatibleCollectionSerializer(abstractType, serializer.GetType(), exampleType); } }
private void BuildCollectionUnpackFrom(TContext context, CollectionTraits traits) { this.EmitMethodPrologue(context, SerializerMethod.UnpackFromCore); TConstruct construct = null; try { Type instanceType; if (typeof(TObject).GetIsInterface() || typeof(TObject).GetIsAbstract()) { instanceType = context.SerializationContext.DefaultCollectionTypes.GetConcreteType(typeof(TObject)); if (instanceType == null) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(TObject)); } } else { instanceType = typeof(TObject); } /* * if (!unpacker.IsArrayHeader) * { * throw SerializationExceptions.NewIsNotArrayHeader(); * } * int capacity = ITEMS_COUNT(unpacker); * TCollection collection = new ...; * this.UnpackToCore(unpacker, array); * return collection; */ var collection = this.DeclareLocal( context, instanceType, "collection" ); var ctor = GetCollectionConstructor(instanceType); var collectionCapacity = this.EmitGetItemsCountExpression(context, context.Unpacker); construct = this.EmitSequentialStatements( context, collection.ContextType, this.EmitCheckIsArrayHeaderExpression(context, context.Unpacker), collection, traits.AddMethod == null ? this.EmitSequentialStatements( context, typeof(void), this.EmitStoreVariableStatement( context, collection, this.EmitCreateNewObjectExpression( context, collection, ctor, ctor.GetParameters().Length == 0 ? NoConstructs : new[] { collectionCapacity } ) ), this.EmitUnpackToSpecifiedCollection(context, instanceType.GetCollectionTraits(), context.Unpacker, collection) ) : this.EmitUnpackCollectionWithUnpackToExpression( context, ctor, collectionCapacity, context.Unpacker, collection ), this.EmitRetrunStatement( context, this.EmitLoadVariableExpression(context, collection) ) ); } finally { this.EmitMethodEpilogue(context, SerializerMethod.UnpackFromCore, construct); } }
protected ObjectReflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members) : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { if (type.GetIsAbstract() || type.GetIsInterface()) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); } this._createInstance = () => Activator.CreateInstance(type); //Expression.Lambda<Func<T>>( // typeof(T).GetIsValueType() // ? Expression.Default(typeof(T)) as Expression // : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes)) // ).Compile(); var isPackable = typeof(IPackable).IsAssignableFrom(type); var isUnpackable = typeof(IUnpackable).IsAssignableFrom(type); if (isPackable && isUnpackable) { this._memberSerializers = null; this._indexMap = null; this._isCollection = null; this._nilImplications = null; this._memberNames = null; } else { this._memberSerializers = members.Select( m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray ( ); this._indexMap = members .Select((m, i) => new KeyValuePair <SerializingMember, int>(m, i)) .Where(kv => kv.Key.Member != null) .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value); this._isCollection = members.Select( m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()). Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray(); // NilImplication validity check foreach (var member in members) { switch (member.Contract.NilImplication) { case NilImplication.Null: { if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name); } break; } } } this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray(); this._memberNames = members.Select(m => m.Contract.Name).ToArray(); } if (isPackable) { this._packToMessage = (target, packer, packingOptions) => { ((IPackable)target).PackToMessage(packer, packingOptions); //typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single().Invoke(target, new object[] { packer, packingOptions }); }; this._memberGetters = null; } else { this._packToMessage = null; this._memberGetters = members.Select <SerializingMember, Func <object, object> >( m => m.Member == null ? (target => null) : CreateMemberGetter(m)).ToArray(); } if (isUnpackable) { this._unpackFromMessage = delegate(ref object target, Unpacker value) { ((IUnpackable)target).UnpackFromMessage(value); }; this._memberSetters = null; } else { this._unpackFromMessage = null; this._memberSetters = members.Select( m => m.Member == null ? delegate(ref object target, object memberValue) { } : m.Member.CanSetValue() ? CreateMemberSetter(m) : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member) ? default(MemberSetter) : ThrowGetOnlyMemberIsInvalid(m.Member) ).ToArray(); } }
protected ObjectExpressionMessagePackSerializer(SerializationContext context, SerializingMember[] members) : base((context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { if (typeof(T).GetIsAbstract() || typeof(T).GetIsInterface()) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(T)); } this._createInstance = Expression.Lambda <Func <T> >( typeof(T).GetIsValueType() ? Expression.Default(typeof(T)) as Expression : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes)) ).Compile(); var isPackable = typeof(IPackable).IsAssignableFrom(typeof(T)); var isUnpackable = typeof(IUnpackable).IsAssignableFrom(typeof(T)); var targetParameter = Expression.Parameter(typeof(T), "target"); if (isPackable && isUnpackable) { this._memberSerializers = null; this._indexMap = null; this._isCollection = null; this._nilImplications = null; this._memberNames = null; } else { this._memberSerializers = members.Select( m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray ( ); this._indexMap = members .Zip(Enumerable.Range(0, members.Length), (m, i) => new KeyValuePair <SerializingMember, int>(m, i)) .Where(kv => kv.Key.Member != null) .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value); this._isCollection = members.Select( m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()). Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray(); // NilImplication validity check foreach (var member in members) { switch (member.Contract.NilImplication) { case NilImplication.Null: { if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name); } break; } } } this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray(); this._memberNames = members.Select(m => m.Contract.Name).ToArray(); } if (isPackable) { var packerParameter = Expression.Parameter(typeof(Packer), "packer"); var optionsParameter = Expression.Parameter(typeof(PackingOptions), "options"); this._packToMessage = Expression.Lambda <Action <T, Packer, PackingOptions> >( Expression.Call( targetParameter, typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single(), packerParameter, optionsParameter ), targetParameter, packerParameter, optionsParameter ).Compile(); this._memberGetters = null; } else { this._packToMessage = null; this._memberGetters = members.Select( m => m.Member == null ? Expression.Lambda <Func <T, object> >( Expression.Constant(null), targetParameter ).Compile() : CreateMemberGetter(targetParameter, m) ).ToArray(); } var refTargetParameter = Expression.Parameter(typeof(T).MakeByRefType(), "target"); if (isUnpackable) { var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker"); this._unpackFromMessage = Expression.Lambda <UnpackFromMessageInvocation>( Expression.Call( refTargetParameter, typeof(T).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single(), unpackerParameter ), refTargetParameter, unpackerParameter ).Compile(); this._memberSetters = null; } else { this._unpackFromMessage = null; var valueParameter = Expression.Parameter(typeof(object), "value"); this._memberSetters = members.Select( m => m.Member == null ? Expression.Lambda <MemberSetter>( Expression.Empty(), refTargetParameter, valueParameter ).Compile() : m.Member.CanSetValue() ? Expression.Lambda <MemberSetter>( Expression.Assign( Expression.PropertyOrField( refTargetParameter, m.Member.Name ), Expression.Call( Metadata._UnpackHelpers.ConvertWithEnsuringNotNull_1Method.MakeGenericMethod(m.Member.GetMemberValueType()), valueParameter, Expression.Constant(m.Member.Name), Expression.Call( // Using RuntimeTypeHandle to avoid WinRT expression tree issue. null, Metadata._Type.GetTypeFromHandle, Expression.Constant(m.Member.DeclaringType.TypeHandle) ) ) ), refTargetParameter, valueParameter ).Compile() : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member) ? default(MemberSetter) : ThrowGetOnlyMemberIsInvalid(m.Member) ).ToArray(); } }
private void BuildMapUnpackFrom(TContext context) { this.EmitMethodPrologue(context, SerializerMethod.UnpackFromCore); TConstruct construct = null; try { Type instanceType; if (typeof(TObject).GetIsInterface() || typeof(TObject).GetIsAbstract()) { instanceType = context.SerializationContext.DefaultCollectionTypes.GetConcreteType(typeof(TObject)); if (instanceType == null) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(TObject)); } } else { instanceType = typeof(TObject); } /* * if (!unpacker.IsMapHeader) * { * throw SerializationExceptions.NewIsNotMapHeader(); * } * int capacity = ITEMS_COUNT(unpacker); * * TDictionary<TKey, TValue> dictionary = new ...; * this.UnpackToCore(unpacker, dictionary); * return dictionary; */ var collection = this.DeclareLocal( context, typeof(TObject), "collection" ); construct = this.EmitSequentialStatements( context, typeof(TObject), this.EmitCheckIsMapHeaderExpression(context, context.Unpacker), collection, this.EmitUnpackCollectionWithUnpackToExpression( context, GetCollectionConstructor(instanceType), this.EmitGetItemsCountExpression(context, context.Unpacker), context.Unpacker, collection ), this.EmitRetrunStatement( context, this.EmitLoadVariableExpression(context, collection) ) ); } finally { this.EmitMethodEpilogue(context, SerializerMethod.UnpackFromCore, construct); } }