/// <summary> /// Initializes a new instance of the <see cref="ContextBasedSerializerEmitter"/> class. /// </summary> /// <param name="targetType">Type of the target.</param> public ContextBasedSerializerEmitter(Type targetType) { Contract.Requires(targetType != null); this._targetType = targetType; this._traits = targetType.GetCollectionTraits(); }
public ReflectionNonGenericDictionaryMessagePackSerializer( SerializationContext ownerContext, Type targetType, CollectionTraits collectionTraits, PolymorphismSchema itemsSchema, SerializationTarget targetInfo ) : base(ownerContext, itemsSchema, targetInfo.GetCapabilitiesForCollection(collectionTraits)) { if (targetInfo.CanDeserialize) { this._factory = ReflectionSerializerHelper.CreateCollectionInstanceFactory <TDictionary, object>(targetInfo.DeserializationConstructor); } else { this._factory = _ => { throw SerializationExceptions.NewCreateInstanceIsNotSupported(targetType); }; } this._isPackable = typeof(IPackable).IsAssignableFrom(targetType ?? typeof(TDictionary)); this._isUnpackable = typeof(IUnpackable).IsAssignableFrom(targetType ?? typeof(TDictionary)); #if FEATURE_TAP this._isAsyncPackable = typeof(IAsyncPackable).IsAssignableFrom(targetType ?? typeof(TDictionary)); this._isAsyncUnpackable = typeof(IAsyncUnpackable).IsAssignableFrom(targetType ?? typeof(TDictionary)); #endif // FEATURE_TAP }
private void BuildCollectionAddItem(TContext context, CollectionTraits traits) { var addItem = this.BaseClass.GetRuntimeMethod(MethodName.AddItem); context.BeginMethodOverride(MethodName.AddItem); context.EndMethodOverride( MethodName.AddItem, traits.CollectionType == CollectionKind.Map ? this.EmitAppendDictionaryItem( context, traits, context.CollectionToBeAdded, addItem.GetParameters()[0].ParameterType, context.KeyToAdd, addItem.GetParameters()[1].ParameterType, context.ValueToAdd, false ) : this.EmitAppendCollectionItem( context, null, traits, context.CollectionToBeAdded, context.ItemToAdd ) ); }
/// <summary> /// Initializes a new instance of the <see cref="ContextBasedSerializerEmitter"/> class. /// </summary> /// <param name="specification">The specification of the serializer.</param> public ContextBasedSerializerEmitter(SerializerSpecification specification) { Contract.Requires(specification != null); this._targetType = specification.TargetType; this._traits = specification.TargetCollectionTraits; }
/// <summary> /// Initializes a new instance of the <see cref="FieldBasedSerializerEmitter"/> class. /// </summary> /// <param name="host">The host <see cref="ModuleBuilder"/>.</param> /// <param name="specification">The specification of the serializer.</param> /// <param name="baseClass">Type of the base class of the serializer.</param> /// <param name="isDebuggable">Set to <c>true</c> when <paramref name="host"/> is debuggable.</param> public FieldBasedSerializerEmitter(ModuleBuilder host, SerializerSpecification specification, Type baseClass, bool isDebuggable) { Contract.Requires(host != null); Contract.Requires(specification != null); Contract.Requires(baseClass != null); Tracer.Emit.TraceEvent(Tracer.EventType.DefineType, Tracer.EventId.DefineType, "Create {0}", specification.SerializerTypeFullName); this._typeBuilder = host.DefineType( specification.SerializerTypeFullName, TypeAttributes.Sealed | TypeAttributes.Public | TypeAttributes.UnicodeClass | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, baseClass ); this._defaultConstructorBuilder = this._typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); this._contextConstructorBuilder = this._typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ConstructorParameterTypes); this._traits = specification.TargetCollectionTraits; var baseType = this._typeBuilder.BaseType; #if DEBUG Contract.Assert(baseType != null, "baseType != null"); #endif this._serializers = new Dictionary <SerializerFieldKey, SerializerFieldInfo>(); this._fieldInfos = new Dictionary <RuntimeFieldHandle, FieldBuilder>(); this._methodBases = new Dictionary <RuntimeMethodHandle, FieldBuilder>(); this._isDebuggable = isDebuggable; #if !SILVERLIGHT && !NETFX_35 if (isDebuggable && SerializerDebugging.DumpEnabled) { SerializerDebugging.PrepareDump(host.Assembly as AssemblyBuilder); } #endif }
public static MessagePackSerializer <T> CreateMapSerializer <T>( SerializationContext context, Type targetType, CollectionTraits traits) { if (traits.DetailedCollectionType == CollectionDetailedKind.GenericDictionary) { return (new ReflectionCollectionSerializer <T>( context, Activator.CreateInstance( typeof(DictionarySerializer <,>).MakeGenericType(traits.ElementType.GetGenericArguments()), context, targetType ) as IMessagePackSerializer )); } else { #if DEBUG && !UNITY Contract.Assert(traits.DetailedCollectionType == CollectionDetailedKind.NonGenericDictionary); #endif // DEBUG && !UNITY return (new ReflectionCollectionSerializer <T>( context, new NonGenericDictionarySerializer(context, targetType) )); } }
/// <summary> /// Create new <see cref="AssemblyBuilderEmittingContext"/> for specified <see cref="Type"/>. /// </summary> /// <param name="targetType">The target type of the serializer.</param> /// <param name="targetTypeCollectionTraits">The collection traits of <paramref name="targetType"/>.</param> /// <param name="serializerBaseClass">The base class of the serializer.</param> /// <returns><see cref="AssemblyBuilderEmittingContext"/>.</returns> public AssemblyBuilderEmittingContext CreateEmittingContext(Type targetType, CollectionTraits targetTypeCollectionTraits, Type serializerBaseClass) { string serializerTypeName, serializerTypeNamespace; DefaultSerializerNameResolver.ResolveTypeName( this._assemblyBuilder == null, targetType, this._namespace, out serializerTypeName, out serializerTypeNamespace ); var spec = new SerializerSpecification( targetType, targetTypeCollectionTraits, serializerTypeName, serializerTypeNamespace ); this._generatedSerializers.Add(spec); return (new AssemblyBuilderEmittingContext( this._context, targetType, targetType.GetIsEnum() ? new Func <SerializerEmitter>(() => this._generatorManager.CreateEnumEmitter(this._context, spec)) : () => this._generatorManager.CreateObjectEmitter(spec, serializerBaseClass) )); }
/// <summary> /// Create new <see cref="AssemblyBuilderEmittingContext"/> for specified <see cref="Type"/>. /// </summary> /// <param name="targetType">The target type of the serializer.</param> /// <param name="targetTypeCollectionTraits">The collection traits of <paramref name="targetType"/>.</param> /// <param name="serializerBaseClass">The base class of the serializer.</param> /// <returns><see cref="AssemblyBuilderEmittingContext"/>.</returns> public AssemblyBuilderEmittingContext CreateEmittingContext( Type targetType, CollectionTraits targetTypeCollectionTraits, Type serializerBaseClass ) { string serializerTypeName, serializerTypeNamespace; DefaultSerializerNameResolver.ResolveTypeName( this._assemblyBuilder == null, targetType, typeof( AssemblyBuilderCodeGenerationContext ).Namespace, out serializerTypeName, out serializerTypeNamespace ); var spec = new SerializerSpecification( targetType, targetTypeCollectionTraits, serializerTypeName, serializerTypeNamespace ); this._generatedSerializers.Add( spec ); return new AssemblyBuilderEmittingContext( this._context, targetType, () => this._generatorManager.CreateEmitter( spec, serializerBaseClass, EmitterFlavor.FieldBased ), () => this._generatorManager.CreateEnumEmitter( this._context, spec, EmitterFlavor.FieldBased ) ); }
public static Action <object, object> GetAddItem(Type targetType, CollectionTraits collectionTraits) #endif // !UNITY { if (collectionTraits.AddMethod == null) { throw new SerializationException( String.Format( CultureInfo.CurrentCulture, "Reflection based serializer only supports collection types which implement interface to add new item such as '{0}' and '{1}'", typeof(ICollection <>).GetFullName(), typeof(IList) ) ); } // CreateDelegate causes AOT error. // So use reflection in AOT environment. #if !AOT || AOT_CHECK try { return(collectionTraits.AddMethod.CreateDelegate(typeof(Action <TCollection, TItem>)) as Action <TCollection, TItem>); } catch (ArgumentException) { #endif // !AOT || AOT_CHECK return((collection, item) => collectionTraits.AddMethod.InvokePreservingExceptionType(collection, item)); #if !AOT || AOT_CHECK } #endif // !AOT || AOT_CHECK }
protected override ExpressionConstruct EmitForEachLoop( ExpressionTreeContext context, CollectionTraits collectionTraits, ExpressionConstruct collection, Func <ExpressionConstruct, ExpressionConstruct> loopBodyEmitter ) { var enumerator = Expression.Variable(collectionTraits.GetEnumeratorMethod.ReturnType, "enumerator"); var current = Expression.Variable(collectionTraits.ElementType, "current"); var moveNextMethod = Metadata._IEnumerator.FindEnumeratorMoveNextMethod(enumerator.Type); var currentProperty = Metadata._IEnumerator.FindEnumeratorCurrentProperty(enumerator.Type, collectionTraits); var endForEach = Expression.Label("END_FOREACH"); return (Expression.Block( new[] { enumerator, current }, Expression.Assign(enumerator, Expression.Call(collection, collectionTraits.GetEnumeratorMethod)), Expression.Loop( Expression.IfThenElse( Expression.Call(enumerator, moveNextMethod), Expression.Block( Expression.Assign(current, Expression.Property(enumerator, currentProperty)), loopBodyEmitter(current) ), Expression.Break(endForEach) ), endForEach ) )); }
public static PropertyInfo FindEnumeratorCurrentProperty( Type enumeratorType, CollectionTraits traits ) { #if DEBUG Contract.Assert( traits.GetEnumeratorMethod != null ); #endif // DEBUG PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty( "Current" ); if ( currentProperty == null ) { if ( enumeratorType == typeof( IDictionaryEnumerator ) ) { currentProperty = Metadata._IDictionaryEnumerator.Entry; } else if ( enumeratorType.GetIsInterface() ) { if ( enumeratorType.GetIsGenericType() && enumeratorType.GetGenericTypeDefinition() == typeof( IEnumerator<> ) ) { currentProperty = typeof( IEnumerator<> ).MakeGenericType( traits.ElementType ).GetProperty( "Current" ); } else { currentProperty = Metadata._IEnumerator.Current; } } } return currentProperty; }
/// <summary> /// Create new <see cref="AssemblyBuilderEmittingContext"/> for specified <see cref="Type"/>. /// </summary> /// <param name="targetType">The target type of the serializer.</param> /// <param name="targetTypeCollectionTraits">The collection traits of <paramref name="targetType"/>.</param> /// <param name="serializerBaseClass">The base class of the serializer.</param> /// <returns><see cref="AssemblyBuilderEmittingContext"/>.</returns> public AssemblyBuilderEmittingContext CreateEmittingContext( Type targetType, CollectionTraits targetTypeCollectionTraits, Type serializerBaseClass ) { string serializerTypeName, serializerTypeNamespace; DefaultSerializerNameResolver.ResolveTypeName( this._assemblyBuilder == null, targetType, this._namespace, out serializerTypeName, out serializerTypeNamespace ); var spec = new SerializerSpecification( targetType, targetTypeCollectionTraits, serializerTypeName, serializerTypeNamespace ); this._generatedSerializers.Add( spec ); return new AssemblyBuilderEmittingContext( this._context, targetType, targetType.GetIsEnum() ? new Func<SerializerEmitter>( () => this._generatorManager.CreateEnumEmitter( this._context, spec ) ) : () => this._generatorManager.CreateObjectEmitter( spec, serializerBaseClass ) ); }
private void BuildCollectionAddItem(TContext context, Type declaringType, CollectionTraits traits) { var addItem = GetCollectionSerializerMethod("AddItem", declaringType); this.EmitMethodPrologue(context, CollectionSerializerMethod.AddItem, addItem); TConstruct construct = null; try { construct = traits.CollectionType == CollectionKind.Map ? this.EmitAppendDictionaryItem( context, traits, context.CollectionToBeAdded, addItem.GetParameters()[0].ParameterType, context.KeyToAdd, addItem.GetParameters()[1].ParameterType, context.ValueToAdd, false ) : this.EmitAppendCollectionItem( context, null, traits, context.CollectionToBeAdded, context.ItemToAdd ); } finally { this.EmitMethodEpilogue(context, CollectionSerializerMethod.AddItem, construct); } }
/// <summary> /// Create new <see cref="AssemblyBuilderEmittingContext"/> for specified <see cref="Type"/>. /// </summary> /// <param name="targetType">The target type of the serializer.</param> /// <param name="targetTypeCollectionTraits">The collection traits of <paramref name="targetType"/>.</param> /// <param name="serializerBaseClass">The base class of the serializer.</param> /// <returns><see cref="AssemblyBuilderEmittingContext"/>.</returns> public AssemblyBuilderEmittingContext CreateEmittingContext(Type targetType, CollectionTraits targetTypeCollectionTraits, Type serializerBaseClass) { string serializerTypeName, serializerTypeNamespace; DefaultSerializerNameResolver.ResolveTypeName( this._assemblyBuilder == null, targetType, typeof(AssemblyBuilderCodeGenerationContext).Namespace, out serializerTypeName, out serializerTypeNamespace ); var spec = new SerializerSpecification( targetType, targetTypeCollectionTraits, serializerTypeName, serializerTypeNamespace ); this._generatedSerializers.Add(spec); return (new AssemblyBuilderEmittingContext( this._context, targetType, () => this._generatorManager.CreateEmitter(spec, serializerBaseClass, EmitterFlavor.FieldBased), () => this._generatorManager.CreateEnumEmitter(this._context, spec, EmitterFlavor.FieldBased) )); }
private TConstruct EmitUnpackToSpecifiedCollection( TContext context, CollectionTraits traitsOfTheCollection, TConstruct unpacker, TConstruct collection ) { var count = this.DeclareLocal( context, typeof(int), "count" ); return (this.EmitSequentialStatements( context, typeof(void), this.EmitCheckIsArrayHeaderExpression(context, context.Unpacker), count, this.EmitStoreVariableStatement( context, count, this.EmitGetItemsCountExpression(context, context.Unpacker) ), this.EmitForLoop( context, count, flc => this.EmitUnpackToCollectionLoopBody(context, flc, traitsOfTheCollection, unpacker, collection) ) )); }
protected override TConstruct EmitForEachLoop(TContext context, CollectionTraits collectionTraits, TConstruct collection, Func <TConstruct, TConstruct> loopBodyEmitter) { Contract.Requires(context != null); Contract.Requires(collection != null); Contract.Requires(loopBodyEmitter != null); Contract.Ensures(Contract.Result <TConstruct>() != null); Contract.Ensures(Contract.Result <TConstruct>().ContextType == typeof(void)); return(default(TConstruct)); }
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(); } } } }
/// <summary> /// Determines that whether built-in serializer for specified type exists or not. /// </summary> /// <param name="type">The type for check.</param> /// <param name="traits">The known <see cref="CollectionTraits"/> of the <paramref name="type"/>.</param> /// <returns> /// <c>true</c> if built-in serializer for specified type exists; <c>false</c>, otherwise. /// </returns> /// <exception cref="System.NotImplementedException"></exception> public bool BuiltInSerializerExists( Type type, CollectionTraits traits ) { if ( type == null ) { throw new ArgumentNullException( "type" ); } return GenericSerializer.IsSupported( type, traits, this._preferReflectionBasedSerializer ) || SerializerRepository.InternalDefault.Contains( type ); }
private void BuildArraySerializer(TContext context, CollectionTraits traits) { this.BuildCollectionPackTo(context, traits); this.BuildCollectionUnpackFrom(context, traits); if (traits.AddMethod != null) { this.BuildCollectionUnpackTo(context, traits); } }
public static Type GetSerializerClass(Type targetType, CollectionTraits traits) { switch (traits.DetailedCollectionType) { case CollectionDetailedKind.GenericEnumerable: { return(typeof(ExpressionCallbackEnumerableMessagePackSerializer <,>).MakeGenericType(targetType, traits.ElementType)); } case CollectionDetailedKind.GenericCollection: case CollectionDetailedKind.GenericSet: case CollectionDetailedKind.GenericList: { return(typeof(ExpressionCallbackCollectionMessagePackSerializer <,>).MakeGenericType(targetType, traits.ElementType)); } case CollectionDetailedKind.GenericDictionary: { var keyValuePairGenericArguments = traits.ElementType.GetGenericArguments(); return (typeof(ExpressionCallbackDictionaryMessagePackSerializer <, ,>).MakeGenericType( targetType, keyValuePairGenericArguments[0], keyValuePairGenericArguments[1] )); } case CollectionDetailedKind.NonGenericEnumerable: { return(typeof(ExpressionCallbackNonGenericEnumerableMessagePackSerializer <>).MakeGenericType(targetType)); } case CollectionDetailedKind.NonGenericCollection: { return(typeof(ExpressionCallbackNonGenericCollectionMessagePackSerializer <>).MakeGenericType(targetType)); } case CollectionDetailedKind.NonGenericList: { return(typeof(ExpressionCallbackNonGenericListMessagePackSerializer <>).MakeGenericType(targetType)); } case CollectionDetailedKind.NonGenericDictionary: { return(typeof(ExpressionCallbackNonGenericDictionaryMessagePackSerializer <>).MakeGenericType(targetType)); } default: { return (targetType.GetIsEnum() ? typeof(ExpressionCallbackEnumMessagePackSerializer <>).MakeGenericType(targetType) : typeof(ExpressionCallbackMessagePackSerializer <>).MakeGenericType(targetType)); } } }
protected UnityEnumerableMessagePackSerializer( SerializationContext ownerContext, Type targetType, CollectionTraits traits, PolymorphismSchema schema ) : base(ownerContext, targetType, traits.ElementType, schema) { this._getCount = traits.CountPropertyGetter; }
public ReflectionCollectionMessagePackSerializer( SerializationContext ownerContext, Type abstractType, Type concreteType, CollectionTraits traits, PolymorphismSchema itemsSchema) : base(ownerContext, abstractType, traits, itemsSchema) { this._factory = ReflectionSerializerHelper.CreateCollectionInstanceFactory(abstractType, concreteType, traits.ElementType); }
public static SerializerEmitter CreateArraySerializerCore(Type targetType, EmitterFlavor emitterFlavor) { Contract.Requires(targetType != null); SerializerEmitter emitter = SerializationMethodGeneratorManager.Get().CreateEmitter(targetType, emitterFlavor); CollectionTraits collectionTraits = targetType.GetCollectionTraits(); CreatePackArrayProceduresCore(targetType, emitter, collectionTraits); CreateUnpackArrayProceduresCore(targetType, emitter, collectionTraits); return(emitter); }
/// <summary> /// Initializes a new instance of the <see cref="FieldBasedSerializerEmitter"/> class. /// </summary> /// <param name="host">The host <see cref="ModuleBuilder"/>.</param> /// <param name="sequence">The sequence number to name new type.</param> /// <param name="targetType">Type of the serialization target.</param> /// <param name="baseClass">Type of the base class of the serializer.</param> /// <param name="isDebuggable">Set to <c>true</c> when <paramref name="host"/> is debuggable.</param> public FieldBasedSerializerEmitter(ModuleBuilder host, int?sequence, Type targetType, Type baseClass, bool isDebuggable) { Contract.Requires(host != null); Contract.Requires(targetType != null); Contract.Requires(baseClass != null); string typeName = #if !NETFX_35 String.Join( Type.Delimiter.ToString(CultureInfo.InvariantCulture), typeof(SerializerEmitter).Namespace, "Generated", IdentifierUtility.EscapeTypeName(targetType) + "Serializer" + sequence ); #else String.Join( Type.Delimiter.ToString(), new string[] { typeof(SerializerEmitter).Namespace, "Generated", IdentifierUtility.EscapeTypeName(targetType) + "Serializer" + sequence } ); #endif Tracer.Emit.TraceEvent(Tracer.EventType.DefineType, Tracer.EventId.DefineType, "Create {0}", typeName); this._typeBuilder = host.DefineType( typeName, TypeAttributes.Sealed | TypeAttributes.Public | TypeAttributes.UnicodeClass | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, baseClass ); this._defaultConstructorBuilder = this._typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); this._contextConstructorBuilder = this._typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ConstructorParameterTypes); this._targetType = targetType; this._traits = targetType.GetCollectionTraits(); var baseType = this._typeBuilder.BaseType; #if DEBUG Contract.Assert(baseType != null, "baseType != null"); #endif this._serializers = new Dictionary <SerializerFieldKey, SerializerFieldInfo>(); this._fieldInfos = new Dictionary <RuntimeFieldHandle, FieldBuilder>(); this._methodBases = new Dictionary <RuntimeMethodHandle, FieldBuilder>(); this._isDebuggable = isDebuggable; #if !SILVERLIGHT && !NETFX_35 if (isDebuggable && SerializerDebugging.DumpEnabled) { SerializerDebugging.PrepareDump(host.Assembly as AssemblyBuilder); } #endif }
/// <summary> /// Initializes a new instance of the <see cref="SerializerBuilder{TContext, TConstruct}"/> class. /// </summary> /// <param name="targetType">The type of serialization target.</param> /// <param name="collectionTraits">The collection traits of the serialization target.</param> protected SerializerBuilder(Type targetType, CollectionTraits collectionTraits) { #if DEBUG Contract.Assert(targetType != null, "targetType != null"); #endif // DEBUG this.TargetType = targetType; this.CollectionTraits = collectionTraits; this.BaseClass = DetermineBaseClass(targetType, collectionTraits); this._nilImplicationHandler = new SerializerBuilderNilImplicationHandler(targetType); }
protected UnityCollectionMessagePackSerializer( SerializationContext ownerContext, Type targetType, CollectionTraits traits, PolymorphismSchema schema, SerializerCapabilities capabilities ) : base(ownerContext, targetType, traits.ElementType, schema, capabilities) { this._getCount = traits.CountPropertyGetter; this._add = traits.AddMethod; }
private void BuildCollectionPackTo(TContext context, CollectionTraits traits) { #if DEBUG Contract.Assert(!typeof(TObject).IsArray); #endif this.EmitMethodPrologue(context, SerializerMethod.PackToCore); TConstruct construct = null; try { if (traits.CountProperty == null) { // IEnumerable but not ICollection var arrayType = traits.ElementType.MakeArrayType(); construct = this.EmitInvokeMethodExpression( context, this.EmitGetSerializerExpression(context, arrayType, null), typeof(MessagePackSerializer <>).MakeGenericType(arrayType).GetMethod("PackTo"), context.Packer, this.EmitInvokeEnumerableToArrayExpression(context, context.PackToTarget, traits.ElementType) ); } else { // ICollection construct = this.EmitSequentialStatements( context, typeof(void), this.EmitPutArrayHeaderExpression( context, this.EmitGetCollectionCountExpression(context, context.PackToTarget, traits) ), this.EmitForEachLoop( context, traits, context.PackToTarget, item => this.EmitSequentialStatements( context, typeof(void), this.EmitPackItemStatements(context, context.Packer, traits.ElementType, NilImplication.Null, null, item, null) ) ) ); } } finally { this.EmitMethodEpilogue(context, SerializerMethod.PackToCore, construct); } }
public ReflectionCollectionMessagePackSerializer( SerializationContext ownerContext, Type abstractType, Type concreteType, CollectionTraits traits, PolymorphismSchema itemsSchema ) : base(ownerContext, abstractType, traits, itemsSchema) { this._factory = ReflectionSerializerHelper.CreateCollectionInstanceFactory(abstractType, concreteType, traits.ElementType); this._isPackable = typeof(IPackable).IsAssignableFrom(concreteType ?? abstractType); this._isUnpackable = typeof(IUnpackable).IsAssignableFrom(concreteType ?? abstractType); }
public ReflectionNonGenericEnumerableMessagePackSerializer( SerializationContext ownerContext, Type abstractType, Type concreteType, CollectionTraits concreteTypeCollectionTraits, PolymorphismSchema itemsSchema ) : base(ownerContext, abstractType, itemsSchema) { this._factory = ReflectionSerializerHelper.CreateCollectionInstanceFactory(abstractType, concreteType, typeof(object)); this._addItem = ReflectionSerializerHelper.GetAddItem(concreteType, concreteTypeCollectionTraits); this._isPackable = typeof(IPackable).IsAssignableFrom(concreteType ?? abstractType); this._isUnpackable = typeof(IUnpackable).IsAssignableFrom(concreteType ?? abstractType); }
/// <summary> /// Creates an <see cref="Expression"/> which represents foreach block. /// </summary> /// <param name="collection">The collection to be enumerated.</param> /// <param name="traits">The traits of the collection.</param> /// <param name="bodyCreator">The body creator. The argument is <c>Current</c> property of the enumerator.</param> /// <returns>An <see cref="Expression"/> which represents foreach block.</returns> public static Expression ForEach(Expression collection, CollectionTraits traits, Func <Expression, Expression> bodyCreator) { /* * var enumerator = collection.GetEnumerator(); * try * { * while(true) * { * if ( enumerator.MoveNext() ) * { * body( enumerator.Current ); * } * else * { * break; * } * } * } * finally * { * var asDisposable = enumerator as IDisposable; * if( asDisposable != null ) * { * asDisposable.Dispose(); * } * } */ var enumeratorVariable = Expression.Variable(traits.GetEnumeratorMethod.ReturnType, "enumerator"); var tryBlock = CreateForEachTry(enumeratorVariable, traits, bodyCreator); var finallyBlock = CreateForEachFinally(enumeratorVariable, traits); return (Expression.Block( new[] { enumeratorVariable }, Expression.Assign(enumeratorVariable, Expression.Call(collection, traits.GetEnumeratorMethod)), finallyBlock == null ? tryBlock : Expression.TryFinally( tryBlock, enumeratorVariable.Type.GetIsValueType() ? finallyBlock : Expression.IfThen( Expression.ReferenceNotEqual(enumeratorVariable, Expression.Constant(null)), finallyBlock ) ) )); }
public AbstractEnumerableMessagePackSerializer( SerializationContext ownerContext, #if !UNITY Type targetType, #else Type abstractType, Type concreteType, CollectionTraits traits, #endif // !UNITY PolymorphismSchema schema ) #if !UNITY : base(ownerContext, schema) #else : base(ownerContext, abstractType, traits, schema, SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom | SerializerCapabilities.UnpackTo)
public AbstractCollectionMessagePackSerializer( SerializationContext ownerContext, #if !UNITY Type targetType, #else Type abstractType, Type concreteType, CollectionTraits traits, #endif // !UNITY PolymorphismSchema schema ) #if !UNITY : base(ownerContext, schema) #else : base(ownerContext, abstractType, traits, schema)
public SerializerSpecification(Type targetType, CollectionTraits targetCollectionTraits, string serializerTypeName, string serializerTypeNamespace) { #if DEBUG Contract.Assert(targetType != null, "targetType != null"); Contract.Assert(serializerTypeName != null, "serializerTypeName != null"); Contract.Assert(serializerTypeNamespace != null, "serializerTypeNamespace != null"); #endif // DEBUG this.TargetType = targetType; this.TargetCollectionTraits = targetCollectionTraits; this.SerializerTypeName = serializerTypeName; this.SerializerTypeNamespace = serializerTypeNamespace; this.SerializerTypeFullName = String.IsNullOrEmpty(serializerTypeNamespace) ? serializerTypeName : serializerTypeNamespace + "." + serializerTypeName; }
public ReflectionEnumerableMessagePackSerializer( SerializationContext ownerContext, Type targetType, CollectionTraits collectionTraits, PolymorphismSchema itemsSchema ) : base(ownerContext, itemsSchema) { this._factory = ReflectionSerializerHelper.CreateCollectionInstanceFactory <TCollection, TItem>(targetType); this._addItem = ReflectionSerializerHelper.GetAddItem <TCollection, TItem>(targetType, collectionTraits); this._isPackable = typeof(IPackable).IsAssignableFrom(targetType ?? typeof(TCollection)); this._isUnpackable = typeof(IUnpackable).IsAssignableFrom(targetType ?? typeof(TCollection)); #if FEATURE_TAP this._isAsyncPackable = typeof(IAsyncPackable).IsAssignableFrom(targetType ?? typeof(TCollection)); this._isAsyncUnpackable = typeof(IAsyncUnpackable).IsAssignableFrom(targetType ?? typeof(TCollection)); #endif // FEATURE_TAP }
public static Func<object, int> CreateGetCount(Type type, CollectionTraits traits) { if (type.IsArray) { var lengthAccessor = type.GetProperty("Length").GetGetMethod(); return t => (int)lengthAccessor.Invoke(t, new object[0]); } else if (traits.CountProperty != null) { var countAccessor = traits.CountProperty.GetGetMethod(); return t => (int)countAccessor.Invoke(t, new object[0]); } else { var countMethod = Metadata._Enumerable.Count1Method.MakeGenericMethod(traits.ElementType); return t => (int)countMethod.Invoke(null, new object[] {t}); } }
public ArrayRecflectionMessagePackSerializer(Type type, SerializationContext context, CollectionTraits traits) : base(type, context, traits) { }
/// <summary> /// Emits 'foreach' statement on the IL stream. /// </summary> /// <param name="il">IL generator to be emitted to.</param> /// <param name="traits"><see cref="CollectionTraits"/> which contains traits of the iterating collection.</param> /// <param name="collection">'collection' argument index.</param> /// <param name="bodyEmitter">Delegate to emit body statement.</param> public static void EmitForEach( TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action<TracingILGenerator, Action> bodyEmitter ) { Contract.Requires( il != null ); Contract.Requires( collection != null ); Contract.Requires( bodyEmitter != null ); var enumerator = il.DeclareLocal( traits.GetEnumeratorMethod.ReturnType, "enumerator" ); // gets enumerator if ( collection.LocalType.IsValueType ) { il.EmitAnyLdloca( collection ); } else { il.EmitAnyLdloc( collection ); } il.EmitAnyCall( traits.GetEnumeratorMethod ); il.EmitAnyStloc( enumerator ); if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) ) { il.BeginExceptionBlock(); } var startLoop = il.DefineLabel( "START_LOOP" ); il.MarkLabel( startLoop ); var endLoop = il.DefineLabel( "END_LOOP" ); var enumeratorType = traits.GetEnumeratorMethod.ReturnType; MethodInfo moveNextMethod = enumeratorType.GetMethod( "MoveNext", Type.EmptyTypes ); PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty( "Current" ); if ( moveNextMethod == null ) { moveNextMethod = Metadata._IEnumerator.MoveNext; } if ( currentProperty == null ) { if ( enumeratorType == typeof( IDictionaryEnumerator ) ) { currentProperty = Metadata._IDictionaryEnumerator.Current; } else if ( enumeratorType.IsInterface ) { if ( enumeratorType.IsGenericType && enumeratorType.GetGenericTypeDefinition() == typeof( IEnumerator<> ) ) { currentProperty = typeof( IEnumerator<> ).MakeGenericType( traits.ElementType ).GetProperty( "Current" ); } else { currentProperty = Metadata._IEnumerator.Current; } } } Contract.Assert( currentProperty != null, enumeratorType.ToString() ); // iterates if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { il.EmitAnyLdloca( enumerator ); } else { il.EmitAnyLdloc( enumerator ); } il.EmitAnyCall( moveNextMethod ); il.EmitBrfalse( endLoop ); bodyEmitter( il, () => { if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { il.EmitAnyLdloca( enumerator ); } else { il.EmitAnyLdloc( enumerator ); } il.EmitGetProperty( currentProperty ); } ); il.EmitBr( startLoop ); il.MarkLabel( endLoop ); // Dispose if ( typeof( IDisposable ).IsAssignableFrom( traits.GetEnumeratorMethod.ReturnType ) ) { il.BeginFinallyBlock(); if ( traits.GetEnumeratorMethod.ReturnType.IsValueType ) { var disposeMethod = traits.GetEnumeratorMethod.ReturnType.GetMethod( "Dispose" ); if ( disposeMethod != null && disposeMethod.GetParameters().Length == 0 && disposeMethod.ReturnType == typeof( void ) ) { il.EmitAnyLdloca( enumerator ); il.EmitAnyCall( disposeMethod ); } else { il.EmitAnyLdloc( enumerator ); il.EmitBox( traits.GetEnumeratorMethod.ReturnType ); il.EmitAnyCall( Metadata._IDisposable.Dispose ); } } else { il.EmitAnyLdloc( enumerator ); il.EmitAnyCall( Metadata._IDisposable.Dispose ); } il.EndExceptionBlock(); } }
private static void CreateMapUnpack( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateMapUnpackFrom( targetType, emitter, traits ); CreateMapUnpackTo( targetType, emitter, traits ); }
private static void CreateMapUnpackTo( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetUnpackToMethodILGenerator(); try { EmitInvokeMapUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdarg( 2 ) ); il.EmitRet(); } finally { il.FlushTrace(); } }
protected SequenceReflectionMessagePackSerializer(Type type, SerializationContext context, CollectionTraits traits) : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { Contract.Assert(type.IsArray || typeof(IEnumerable).IsAssignableFrom(type), type + " is not array nor IEnumerable"); this._traits = traits; this._elementSerializer = context.GetSerializer(traits.ElementType); this._getCount = ReflectionSerializerLogics.CreateGetCount(type, traits); //var packerParameter = Expression.Parameter(typeof(Packer), "packer"); //var objectTreeParameter = Expression.Parameter(typeof(T), "objectTree"); //var elementSerializerParameter = Expression.Parameter(typeof(IMessagePackSerializer), "elementSerializer"); this._packToCore = (Packer packer, object objectTree, IMessagePackSerializer elementSerializer) => { var length = this._getCount(objectTree); packer.PackArrayHeader(length); foreach (var item in (IEnumerable)objectTree) { elementSerializer.PackTo(packer, item); } }; /* * for ( int i = 0; i < count; i++ ) * { * if ( !unpacker.Read() ) * { * throw SerializationExceptions.NewMissingItem( i ); * } * * T item; * if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * item = this.ElementSerializer.UnpackFrom( unpacker ); * } * else * { * using ( Unpacker subtreeUnpacker = unpacker.ReadSubtree() ) * { * item = this.ElementSerializer.UnpackFrom( subtreeUnpacker ); * } * } * * instance[ i ] = item; -- OR -- instance.Add( item ); * } */ // FIXME: use UnpackHelper if (type.IsArray) { var arrayUnpackerMethod = _UnpackHelpers.UnpackArrayTo_1.MakeGenericMethod(traits.ElementType); this._unpackToCore = (Unpacker unpacker, object instance, IMessagePackSerializer elementSerializer) => { arrayUnpackerMethod.Invoke(null, new object[] { unpacker, elementSerializer, instance }); }; } else { this._unpackToCore = (Unpacker unpacker, object instance, IMessagePackSerializer elementSerializer) => { var count = UnpackHelpers.GetItemsCount(unpacker); for (int i = 0; i < count; i++) { if (!unpacker.Read()) { throw SerializationExceptions.NewMissingItem(i); } object item; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { item = elementSerializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { item = elementSerializer.UnpackFrom(subtreeUnpacker); } } traits.AddMethod.Invoke(instance, new object[] { item }); } }; } }
private static void CreateUnpackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateArrayUnpackFrom( targetType, emitter, traits ); CreateArrayUnpackTo( targetType, emitter, traits ); }
private static void EmitInvokeArrayUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting ) { il.EmitAnyLdarg( unpackerArgumentIndex ); var serializerGetting = emitter.RegisterSerializer( traits.ElementType ); if ( targetType.IsArray ) { // Array /* * UnpackHelpers.UnpackArrayTo( unpacker, GET_SERIALIZER, collection ); */ serializerGetting( il, 0 ); loadCollectionEmitting( il ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackArrayTo_1.MakeGenericMethod( traits.ElementType ) ); } else if ( targetType.IsGenericType ) { serializerGetting( il, 0 ); loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) ) { // with void Add( T item ) /* * Action<T> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition ); */ var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<> ).MakeGenericType( itemType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_1.MakeGenericMethod( itemType ) ); } else { // with TDiscarded Add( T item ) /* * Func<T, TDiscarded> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition ); */ var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType; var discardingType = traits.AddMethod.ReturnType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( itemType, discardingType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_2.MakeGenericMethod( itemType, discardingType ) ); } } else { loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) ) { // with void Add( object item ) /* * Action<object> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition ); */ EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<object> ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo ); } else { // with TDiscarded Add( object item ) /* * Func<TDiscarded> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition ); */ var discardingType = traits.AddMethod.ReturnType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( typeof( object ), discardingType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo_1.MakeGenericMethod( discardingType ) ); } } }
private static void CreateMapPack( Type targetType, SerializerEmitter emiter, CollectionTraits traits ) { var il = emiter.GetPackToMethodILGenerator(); try { /* * int count = ((ICollection<KeyValuePair<string, DateTime>>)dictionary).Count; * packer.PackMapHeader(count); * foreach (KeyValuePair<string, DateTime> current in dictionary) * { * this._serializer0.PackTo(packer, current.Key); * this._serializer1.PackTo(packer, current.Value); * } */ var collection = il.DeclareLocal( targetType, "collection" ); var item = il.DeclareLocal( traits.ElementType, "item" ); var keyProperty = traits.ElementType.GetProperty( "Key" ); var valueProperty = traits.ElementType.GetProperty( "Value" ); // This instruction is always ldarg, not to be ldarga. il.EmitAnyLdarg( 2 ); il.EmitAnyStloc( collection ); var count = il.DeclareLocal( typeof( int ), "count" ); EmitLoadTarget( targetType, il, collection ); il.EmitGetProperty( traits.CountProperty ); il.EmitAnyStloc( count ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( count ); il.EmitAnyCall( Metadata._Packer.PackMapHeader ); il.EmitPop(); Emittion.EmitForEach( il, traits, collection, ( il0, getCurrentEmitter ) => { if ( traits.ElementType.IsGenericType ) { Contract.Assert( traits.ElementType.GetGenericTypeDefinition() == typeof( KeyValuePair<,> ) ); getCurrentEmitter(); il0.EmitAnyStloc( item ); Emittion.EmitSerializeValue( emiter, il0, 1, traits.ElementType.GetGenericArguments()[ 0 ], null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloca( item ); il1.EmitGetProperty( keyProperty ); } ); Emittion.EmitSerializeValue( emiter, il0, 1, traits.ElementType.GetGenericArguments()[ 1 ], null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloca( item ); il1.EmitGetProperty( valueProperty ); } ); } else { Contract.Assert( traits.ElementType == typeof( DictionaryEntry ) ); getCurrentEmitter(); il0.EmitAnyStloc( item ); Emittion.EmitSerializeValue( emiter, il0, 1, typeof( MessagePackObject ), null, NilImplication.MemberDefault, il1 => { il0.EmitAnyLdloca( item ); il0.EmitGetProperty( Metadata._DictionaryEntry.Key ); il0.EmitUnbox_Any( typeof( MessagePackObject ) ); } ); Emittion.EmitSerializeValue( emiter, il0, 1, typeof( MessagePackObject ), null, NilImplication.MemberDefault, il1 => { il0.EmitAnyLdloca( item ); il0.EmitGetProperty( Metadata._DictionaryEntry.Value ); il0.EmitUnbox_Any( typeof( MessagePackObject ) ); } ); } } ); il.EmitRet(); } finally { il.FlushTrace(); } }
private static void CreatePackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetPackToMethodILGenerator(); try { // Array if ( targetType.IsArray ) { /* * // array * packer.PackArrayHeader( length ); * for( int i = 0; i < length; i++ ) * { * this._serializer.PackTo( packer, collection[ i ] ); * } */ var length = il.DeclareLocal( typeof( int ), "length" ); il.EmitAnyLdarg( 2 ); il.EmitLdlen(); il.EmitAnyStloc( length ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( length ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitFor( il, length, ( il0, i ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdarg( 2 ); il1.EmitAnyLdloc( i ); il1.EmitLdelem( traits.ElementType ); } ); } ); } else if ( traits.CountProperty == null ) { /* * array = collection.ToArray(); * packer.PackArrayHeader( length ); * for( int i = 0; i < length; i++ ) * { * this._serializer.PackTo( packer, array[ i ] ); * } */ var array = il.DeclareLocal( traits.ElementType.MakeArrayType(), "array" ); EmitLoadTarget( targetType, il, 2 ); il.EmitAnyCall( Metadata._Enumerable.ToArray1Method.MakeGenericMethod( traits.ElementType ) ); il.EmitAnyStloc( array ); var length = il.DeclareLocal( typeof( int ), "length" ); il.EmitAnyLdloc( array ); il.EmitLdlen(); il.EmitAnyStloc( length ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( length ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitFor( il, length, ( il0, i ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloc( array ); il1.EmitAnyLdloc( i ); il1.EmitLdelem( traits.ElementType ); } ); } ); } else { /* * // Enumerable * packer.PackArrayHeader( collection.Count ); * foreach( var item in list ) * { * this._serializer.PackTo( packer, array[ i ] ); * } */ var collection = il.DeclareLocal( targetType, "collection" ); // This instruction always ldarg, not to be ldarga il.EmitAnyLdarg( 2 ); il.EmitAnyStloc( collection ); var count = il.DeclareLocal( typeof( int ), "count" ); EmitLoadTarget( targetType, il, 2 ); il.EmitGetProperty( traits.CountProperty ); il.EmitAnyStloc( count ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( count ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitForEach( il, traits, collection, ( il0, getCurrentEmitter ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, _ => getCurrentEmitter() ); } ); } il.EmitRet(); } finally { il.FlushTrace(); } }
private static void CreateArrayUnpackFrom( SerializationContext context, Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetUnpackFromMethodILGenerator(); var localHolder = new LocalVariableHolder( il ); var instanceType = targetType; try { if ( targetType.IsInterface || targetType.IsAbstract ) { instanceType = context.DefaultCollectionTypes.GetConcreteType( targetType ); if ( instanceType == null ) { il.EmitTypeOf( targetType ); il.EmitAnyCall( SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod ); il.EmitThrow(); return; } } /* * if (!unpacker.IsArrayHeader) * { * throw SerializationExceptions.NewIsNotArrayHeader(); * } * * TCollection collection = new ...; * this.UnpackToCore(unpacker, array); * return collection; */ il.EmitAnyLdarg( 1 ); il.EmitGetProperty( Metadata._Unpacker.IsArrayHeader ); var endIf = il.DefineLabel( "END_IF" ); il.EmitBrtrue_S( endIf ); il.EmitAnyCall( SerializationExceptions.NewIsNotArrayHeaderMethod ); il.EmitThrow(); il.MarkLabel( endIf ); var collection = localHolder.GetDeserializingCollection( instanceType ); // Emit newobj, newarr, or call ValueType..ctor() Emittion.EmitConstruction( il, collection, il0 => Emittion.EmitGetUnpackerItemsCountAsInt32( il0, 1, localHolder ) ); EmitInvokeArrayUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdloc( collection ) ); il.EmitAnyLdloc( collection ); il.EmitRet(); } finally { il.FlushTrace(); } }
public MapReflectionMessagePackSerializer(Type type, SerializationContext context, CollectionTraits traits) : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { Contract.Assert(typeof(IEnumerable).IsAssignableFrom(type), type + " is IEnumerable"); Contract.Assert(traits.ElementType == typeof(DictionaryEntry) || (traits.ElementType.GetIsGenericType() && traits.ElementType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)), "Element type " + traits.ElementType + " is not KeyValuePair<TKey,TValue>."); this._traits = traits; this._keySerializer = traits.ElementType.GetIsGenericType() ? context.GetSerializer(traits.ElementType.GetGenericArguments()[0]) : context.GetSerializer(typeof(MessagePackObject)); this._valueSerializer = traits.ElementType.GetIsGenericType() ? context.GetSerializer(traits.ElementType.GetGenericArguments()[1]) : context.GetSerializer(typeof(MessagePackObject)); this._getCount = ReflectionSerializerLogics.CreateGetCount(type, traits); 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]); } var keyType = traits.ElementType.GetIsGenericType() ? traits.ElementType.GetGenericArguments()[0] : typeof(MessagePackObject); var valueType = traits.ElementType.GetIsGenericType() ? traits.ElementType.GetGenericArguments()[1] : typeof(MessagePackObject); var keyProperty = traits.ElementType.GetProperty("Key"); var valueProperty = traits.ElementType.GetProperty("Value"); this._packToCore = (Packer packer, object objectTree, IMessagePackSerializer keySerializer, IMessagePackSerializer valueSerializer) => { packer.PackMapHeader(this._getCount(objectTree)); foreach (var kvp in (IEnumerable)objectTree) { keySerializer.PackTo(packer, keyProperty.GetValue(kvp, new object[0])); valueSerializer.PackTo(packer, valueProperty.GetValue(kvp, new object[0])); } }; if (traits.ElementType.GetIsGenericType()) { /* * UnpackHelpers.UnpackMapTo<TKey,TValue>( unpacker, keySerializer, valueSerializer, instance ); */ var unpackMapToMethod = Metadata._UnpackHelpers.UnpackMapTo_2; //.MakeGenericMethod(keyType, valueType); this._unpackToCore = (Unpacker unpacker, object objectTree, IMessagePackSerializer keySerializer, IMessagePackSerializer valueSerializer) => { unpackMapToMethod.Invoke(null, new object[] { unpacker, keySerializer, valueSerializer, objectTree }); }; } else { /* * UnpackHelpers.UnpackNonGenericMapTo( unpacker, instance ); */ this._unpackToCore = (Unpacker unpacker, object objectTree, IMessagePackSerializer keySerializer, IMessagePackSerializer valueSerializer) => UnpackHelpers.UnpackMapTo(unpacker, (IDictionary)objectTree); } }
private static void EmitInvokeMapUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting ) { il.EmitAnyLdarg( unpackerArgumentIndex ); if ( traits.ElementType.IsGenericType ) { var keyType = traits.ElementType.GetGenericArguments()[ 0 ]; var valueType = traits.ElementType.GetGenericArguments()[ 1 ]; var keySerializerGetting = emitter.RegisterSerializer( keyType ); var valueSerializerGetting = emitter.RegisterSerializer( valueType ); keySerializerGetting( il, 0 ); valueSerializerGetting( il, 0 ); loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } il.EmitAnyCall( Metadata._UnpackHelpers.UnpackMapTo_2.MakeGenericMethod( keyType, valueType ) ); } else { loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericMapTo ); } }
private static void CreateMapUnpackFrom( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetUnpackFromMethodILGenerator(); try { /* * if (!unpacker.IsMapHeader) * { * throw SerializationExceptions.NewIsNotMapHeader(); * } * * TDictionary<TKey, TValue> dictionary = new ...; * this.UnpackToCore(unpacker, dictionary); * return dictionary; */ if ( targetType.IsInterface || targetType.IsAbstract ) { il.EmitTypeOf( targetType ); il.EmitAnyCall( SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod ); il.EmitThrow(); return; } il.EmitAnyLdarg( 1 ); il.EmitGetProperty( Metadata._Unpacker.IsMapHeader ); var endIf = il.DefineLabel( "END_IF" ); il.EmitBrtrue_S( endIf ); il.EmitAnyCall( SerializationExceptions.NewIsNotMapHeaderMethod ); il.EmitThrow(); il.MarkLabel( endIf ); var collection = il.DeclareLocal( targetType, "collection" ); Emittion.EmitConstruction( il, collection, il0 => Emittion.EmitGetUnpackerItemsCountAsInt32( il0, 1 ) ); EmitInvokeMapUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdloc( collection ) ); il.EmitAnyLdloc( collection ); il.EmitRet(); } finally { il.FlushTrace(); } }