private void Invoke(TracingILGenerator il)
        {
            ConstructorInfo asConsctructor;

            if ((asConsctructor = this._method as ConstructorInfo) != null)
            {
                if (asConsctructor.DeclaringType.GetIsValueType())
                {
                    this._target.LoadValue(il, true);
                    foreach (var argument in this._arguments)
                    {
                        argument.LoadValue(il, false);
                    }

                    il.EmitCallConstructor(asConsctructor);

                    // For compatibility to ref type.
                    this._target.LoadValue(il, false);
                }
                else
                {
                    foreach (var argument in this._arguments)
                    {
                        argument.LoadValue(il, false);
                    }

                    il.EmitNewobj(asConsctructor);
                }
            }
            else
            {
                // method
                if (!this._method.IsStatic)
                {
                    this._target.LoadValue(il, this._target.ContextType.GetIsValueType());
                }

                foreach (var argument in this._arguments)
                {
                    argument.LoadValue(il, false);
                }

                if (this._method.IsStatic || this._target.ContextType.GetIsValueType())
                {
                    il.EmitCall(this._method as MethodInfo);
                }
                else
                {
                    il.EmitCallvirt(this._method as MethodInfo);
                }
            }
        }
        /// <summary>
        ///		Emits helper function to avoid lexical closure emitting.
        /// </summary>
        /// <param name="il"><see cref="TracingILGenerator"/>.</param>
        /// <param name="targetOperation"><see cref="MethodInfo"/> of the method to be invoked.</param>
        /// <param name="tupleTypes">The array of <see cref="Type"/> of nested tuples. The outermost is the first, innermost is the last.</param>
        /// <param name="itemTypes">The array of <see cref="Type"/> of flatten tuple items.</param>
        private static void EmitPrivateInvoke(TracingILGenerator il, MethodInfo targetOperation, IList <Type> tupleTypes, Type[] itemTypes)
        {
            /*
             * private void/T PrivateInvoke( object state )
             * {
             *		T result;
             *		Dispatcher.BeginOperation();
             *		try
             *		{
             *			var tuple = state as Tuple<...>;
             *			result =
             *				tuple.Item1.Target(
             *					tuple.Item2,
             *						:
             *					tuple.Rest.Rest....ItemN
             *				);
             *		}
             *		catch( TheradAbortException )
             *		{
             *			Dispatcher.HandleThreadAbortException( ex );
             *		}
             *		finally
             *		{
             *			Dispatcher.EndOperation();
             *		}
             *
             *		return result;
             * }
             */
            var tuple  = il.DeclareLocal(tupleTypes.First(), "tuple");
            var result = targetOperation.ReturnType == typeof(void) ? null : il.DeclareLocal(targetOperation.ReturnType, "result");

            il.EmitAnyLdarg(0);
            il.EmitCall(_dispatcherBeginOperationMethod);
            il.BeginExceptionBlock();

            il.EmitAnyLdarg(1);
            il.EmitIsinst(tupleTypes.First());
            il.EmitAnyStloc(tuple);

            int depth = -1;

            for (int i = 0; i < itemTypes.Length; i++)
            {
                if (i % 7 == 0)
                {
                    depth++;
                }

                il.EmitAnyLdloc(tuple);

                for (int j = 0; j < depth; j++)
                {
                    // .TRest.TRest ...
                    var rest = tupleTypes[j].GetProperty("Rest");
                    il.EmitGetProperty(rest);
                }

                var itemn = tupleTypes[depth].GetProperty("Item" + ((i % 7) + 1));
                il.EmitGetProperty(itemn);
            }

            il.EmitAnyCall(targetOperation);
            if (targetOperation.ReturnType != typeof(void))
            {
                il.EmitAnyStloc(result);
            }

            il.BeginCatchBlock(typeof(ThreadAbortException));
            var ex = il.DeclareLocal(typeof(ThreadAbortException), "ex");

            il.EmitAnyStloc(ex);
            il.EmitAnyLdarg(0);
            il.EmitAnyLdloc(ex);
            il.EmitCall(_dispatcherHandleThreadAbortExceptionMethod);

            il.BeginFinallyBlock();
            il.EmitAnyLdarg(0);
            il.EmitCall(_dispatcherEndOperationMethod);
            il.EndExceptionBlock();

            if (targetOperation.ReturnType != typeof(void))
            {
                il.EmitAnyLdloc(result);
            }

            il.EmitRet();
        }
Beispiel #3
0
        private void Invoke(TracingILGenerator il)
        {
            ConstructorInfo asConsctructor;

            if ((asConsctructor = this._method as ConstructorInfo) != null)
            {
                if (asConsctructor.DeclaringType.GetIsValueType())
                {
                    this._target.LoadValue(il, true);
                    foreach (var argument in this._arguments)
                    {
                        argument.LoadValue(il, false);
                    }

                    il.EmitCallConstructor(asConsctructor);

                    // For compatibility to ref type.
                    this._target.LoadValue(il, false);
                }
                else
                {
                    foreach (var argument in this._arguments)
                    {
                        argument.LoadValue(il, false);
                    }

                    il.EmitNewobj(asConsctructor);
                }
            }
            else
            {
                // method
                if (!this._method.IsStatic)
                {
                    this._target.LoadValue(il, this._target.ContextType.ResolveRuntimeType().GetIsValueType());
                }

                foreach (var argument in this._arguments)
                {
                    argument.LoadValue(il, false);
                }

                if (this._method.IsStatic || this._target.ContextType.ResolveRuntimeType().GetIsValueType())
                {
                    il.EmitCall(this._method as MethodInfo);
                }
                else if (this._interface != null)
                {
                    // Explicit interface impl
                    il.EmitCallvirt(
                        this._interface.GetRuntimeMethod(
                            this._method.Name.Substring(this._method.Name.LastIndexOf('.') + 1),
                            this._method.GetParameters().Select(p => p.ParameterType).ToArray()
                            )
                        );
                }
                else
                {
                    il.EmitCallvirt(this._method as MethodInfo);
                }
            }
        }
        public override Func <SerializationContext, PolymorphismSchema, MessagePackSerializer <T> > CreateConstructor <T>()
        {
            if (!this._typeBuilder.IsCreated())
            {
                /*
                 *	.ctor() : this(null)
                 *	{}
                 */
                /*
                 *	.ctor( SerializationContext context )
                 *	  : base( ( context ?? SerializationContext.Default ).CompabilityOptions.PackerCompatibilityOptions )
                 *	{
                 *		this._serializer0 = context.GetSerializer<T0>();
                 *		this._serializer1 = context.GetSerializer<T1>();
                 *		this._serializer2 = context.GetSerializer<T2>();
                 *			:
                 *	}
                 */
                // default
                {
                    var il = this._defaultConstructorBuilder.GetILGenerator();
                    // : this(null)
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldnull);
                    il.Emit(OpCodes.Call, this._contextConstructorBuilder);
                    il.Emit(OpCodes.Ret);
                }

                // context
                {
                    var il = new TracingILGenerator(this._contextConstructorBuilder, TextWriter.Null, this._isDebuggable);
                    // : base()
                    il.EmitLdarg_0();
                    il.EmitLdarg_1();
#if DEBUG
                    Contract.Assert(this._typeBuilder.BaseType != null, "this._typeBuilder.BaseType != null");
#endif
                    if (this._traits.CollectionType == CollectionKind.NotCollection)
                    {
                        il.EmitCallConstructor(
                            this._typeBuilder.BaseType.GetConstructor(
                                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, ConstructorParameterTypes, null
                                )
                            );
                    }
                    else
                    {
                        il.EmitCall(this._restoreSchemaMethodBuilder);
                        il.EmitCallConstructor(
                            this._typeBuilder.BaseType.GetConstructor(
                                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CollectionConstructorParameterTypes, null
                                )
                            );
                    }

                    // this._serializerN = context.GetSerializer<T>();
                    foreach (var entry in this._serializers)
                    {
                        var        targetType = Type.GetTypeFromHandle(entry.Key.TypeHandle);
                        MethodInfo getMethod  = Metadata._SerializationContext.GetSerializer1_Parameter_Method.MakeGenericMethod(targetType);

                        il.EmitLdarg_0();
                        il.EmitLdarg_1();
                        if (targetType.GetIsEnum())
                        {
                            il.EmitLdarg_1();
                            il.EmitTypeOf(targetType);
                            il.EmitAnyLdc_I4(( int )entry.Key.EnumSerializationMethod);
                            il.EmitCall(Metadata._EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethodMethod);
                            il.EmitBox(typeof(EnumSerializationMethod));
                        }
                        else if (DateTimeMessagePackSerializerHelpers.IsDateTime(targetType))
                        {
                            il.EmitLdarg_1();
                            il.EmitAnyLdc_I4(( int )entry.Key.DateTimeConversionMethod);
                            il.EmitCall(Metadata._DateTimeMessagePackSerializerHelpers.DetermineDateTimeConversionMethodMethod);
                            il.EmitBox(typeof(DateTimeConversionMethod));
                        }
                        else
                        {
                            if (entry.Key.PolymorphismSchema == null)
                            {
                                il.EmitLdnull();
                            }
                            else
                            {
                                entry.Value.SchemaProvider(il);
                            }
                        }

                        il.EmitCallvirt(getMethod);
                        il.EmitStfld(entry.Value.Field);
                    }

                    foreach (var entry in this._fieldInfos)
                    {
                        il.EmitLdarg_0();
                        il.EmitLdtoken(FieldInfo.GetFieldFromHandle(entry.Key));
                        il.EmitCall(Metadata._FieldInfo.GetFieldFromHandle);
                        il.EmitStfld(entry.Value);
                    }

                    foreach (var entry in this._methodBases)
                    {
                        il.EmitLdarg_0();
                        il.EmitLdtoken(MethodBase.GetMethodFromHandle(entry.Key));
                        il.EmitCall(Metadata._MethodBase.GetMethodFromHandle);
                        il.EmitStfld(entry.Value);
                    }

                    il.EmitRet();
                }
            }

            var ctor             = this._typeBuilder.CreateType().GetConstructor(ConstructorParameterTypes);
            var contextParameter = Expression.Parameter(typeof(SerializationContext), "context");
            var schemaParameter  = Expression.Parameter(typeof(PolymorphismSchema), "schema");
#if DEBUG
            Contract.Assert(ctor != null, "ctor != null");
#endif
            return
                (Expression.Lambda <Func <SerializationContext, PolymorphismSchema, MessagePackSerializer <T> > >(
                     Expression.New(
                         ctor,
                         contextParameter
                         ),
                     contextParameter,
                     schemaParameter
                     ).Compile());
        }
        private void CreateContextfulObjectConstructor(
            AssemblyBuilderEmittingContext context,
            Type baseType,
            TracingILGenerator il,
            Func <ILConstruct> packActionListInitializerProvider,
            Func <ILConstruct> packActionTableInitializerProvider,
            Func <ILConstruct> unpackActionListInitializerProvider,
            Func <ILConstruct> unpackActionTableInitializerProvider,
#if FEATURE_TAP
            Func <ILConstruct> packAsyncActionListInitializerProvider,
            Func <ILConstruct> packAsyncActionTableInitializerProvider,
            Func <ILConstruct> unpackAsyncActionListInitializerProvider,
            Func <ILConstruct> unpackAsyncActionTableInitializerProvider,
#endif // FEATURE_TAP
            Func <ILConstruct> memberNamesInitializerProvider,
            Func <ILConstruct> unpackToInitializerProvider
            )
        {
            /*
             *	.ctor( SerializationContext context )
             *	  : base( ( context ?? SerializationContext.Default ).CompabilityOptions.PackerCompatibilityOptions )
             *	{
             *		this._serializer0 = context.GetSerializer<T0>();
             *		this._serializer1 = context.GetSerializer<T1>();
             *		this._serializer2 = context.GetSerializer<T2>();
             *			:
             *	}
             */
            // : base()
            il.EmitLdarg_0();
            il.EmitLdarg_1();
            if (this._specification.TargetCollectionTraits.CollectionType == CollectionKind.NotCollection)
            {
                il.EmitCallConstructor(
                    baseType.GetRuntimeConstructor(ConstructorParameterTypes)
                    );
            }
            else
            {
                il.EmitCall(this._methodTable[MethodName.RestoreSchema]);
                il.EmitCallConstructor(
                    baseType.GetRuntimeConstructor(CollectionConstructorParameterTypes)
                    );
            }

            // this._serializerN = context.GetSerializer<T>();
            foreach (var entry in this._serializers)
            {
                var        targetType = Type.GetTypeFromHandle(entry.Key.TypeHandle);
                MethodInfo getMethod  = Metadata._SerializationContext.GetSerializer1_Parameter_Method.MakeGenericMethod(targetType);

                il.EmitLdarg_0();
                il.EmitLdarg_1();
                if (targetType.GetIsEnum())
                {
                    il.EmitLdarg_1();
                    il.EmitTypeOf(targetType);
                    il.EmitAnyLdc_I4(( int )entry.Key.EnumSerializationMethod);
                    il.EmitCall(Metadata._EnumMessagePackSerializerHelpers.DetermineEnumSerializationMethodMethod);
                    il.EmitBox(typeof(EnumSerializationMethod));
                }
                else if (DateTimeMessagePackSerializerHelpers.IsDateTime(targetType))
                {
                    il.EmitLdarg_1();
                    il.EmitAnyLdc_I4(( int )entry.Key.DateTimeConversionMethod);
                    il.EmitCall(Metadata._DateTimeMessagePackSerializerHelpers.DetermineDateTimeConversionMethodMethod);
                    il.EmitBox(typeof(DateTimeConversionMethod));
                }
                else
                {
                    if (entry.Key.PolymorphismSchema == null)
                    {
                        il.EmitLdnull();
                    }
                    else
                    {
                        entry.Value.SchemaProvider(il);
                    }
                }

                il.EmitCallvirt(getMethod);
                il.EmitStfld(entry.Value.Field);
            }

            foreach (var entry in this._cachedFieldInfos)
            {
                il.EmitLdarg_0();
                il.EmitLdtoken(entry.Value.Target);
                il.EmitLdtoken(entry.Value.Target.DeclaringType);
                il.EmitCall(Metadata._FieldInfo.GetFieldFromHandle);
                il.EmitStfld(entry.Value.StorageFieldBuilder);
            }

            foreach (var entry in this._cachedMethodBases)
            {
                il.EmitLdarg_0();
                il.EmitLdtoken(entry.Value.Target);
                il.EmitLdtoken(entry.Value.Target.DeclaringType);
                il.EmitCall(Metadata._MethodBase.GetMethodFromHandle);
                il.EmitStfld(entry.Value.StorageFieldBuilder);
            }

            if (packActionListInitializerProvider != null)
            {
                packActionListInitializerProvider().Evaluate(il);
            }

#if FEATURE_TAP
            if (packAsyncActionListInitializerProvider != null)
            {
                packAsyncActionListInitializerProvider().Evaluate(il);
            }
#endif // FEATURE_TAP

            if (packActionTableInitializerProvider != null)
            {
                packActionTableInitializerProvider().Evaluate(il);
            }

#if FEATURE_TAP
            if (packAsyncActionTableInitializerProvider != null)
            {
                packAsyncActionTableInitializerProvider().Evaluate(il);
            }
#endif // FEATURE_TAP

            if (unpackActionListInitializerProvider != null)
            {
                unpackActionListInitializerProvider().Evaluate(il);
            }

#if FEATURE_TAP
            if (unpackAsyncActionListInitializerProvider != null)
            {
                unpackAsyncActionListInitializerProvider().Evaluate(il);
            }
#endif // FEATURE_TAP

            if (unpackActionTableInitializerProvider != null)
            {
                unpackActionTableInitializerProvider().Evaluate(il);
            }

#if FEATURE_TAP
            if (unpackAsyncActionTableInitializerProvider != null)
            {
                unpackAsyncActionTableInitializerProvider().Evaluate(il);
            }
#endif // FEATURE_TAP

            if (memberNamesInitializerProvider != null)
            {
                memberNamesInitializerProvider().Evaluate(il);
            }

            if (unpackToInitializerProvider != null)
            {
                unpackToInitializerProvider().Evaluate(il);
            }

            foreach (var cachedDelegateInfo in context.GetCachedDelegateInfos())
            {
                // this for stfld
                il.EmitLdargThis();

                var delegateType = cachedDelegateInfo.BackingField.FieldType.ResolveRuntimeType();

                // Declare backing field now.
                var field = context.GetDeclaredField(cachedDelegateInfo.BackingField.FieldName).ResolveRuntimeField();

                if (cachedDelegateInfo.IsThisInstance)
                {
                    il.EmitLdargThis();
                }
                else
                {
                    il.EmitLdnull();
                }

                // OK this should not be ldvirtftn because target is private or static.
                il.EmitLdftn(cachedDelegateInfo.TargetMethod.ResolveRuntimeMethod());
                // call extern .ctor(Object, void*)
                il.EmitNewobj(delegateType.GetConstructors().Single());

                il.EmitStfld(field);
            }

            il.EmitRet();
        }
        protected sealed override MessagePackSerializer <TObject> CreateSerializer(SerializingMember[] entries)
        {
            MessagePackSerializer <TObject> serializer;

            using (SerializerEmitter emitter = this._generatorManager.CreateEmitter(typeof(TObject), this._emitterFlavor))
            {
                try
                {
                    TracingILGenerator packToMethodILGenerator = emitter.GetPackToMethodILGenerator();
                    try
                    {
                        if (typeof(IPackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).IsValueType)
                            {
                                packToMethodILGenerator.EmitAnyLdarga(2);
                            }
                            else
                            {
                                packToMethodILGenerator.EmitAnyLdarg(2);
                            }
                            packToMethodILGenerator.EmitAnyLdarg(1);
                            packToMethodILGenerator.EmitLdnull();
                            packToMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single <MethodInfo>());
                            packToMethodILGenerator.EmitRet();
                        }
                        else
                        {
                            this.EmitPackMembers(emitter, packToMethodILGenerator, entries);
                        }
                    }
                    finally
                    {
                        packToMethodILGenerator.FlushTrace();
                    }
                    TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();
                    try
                    {
                        LocalBuilder target = unpackFromMethodILGenerator.DeclareLocal(typeof(TObject), "result");
                        Emittion.EmitConstruction(unpackFromMethodILGenerator, target, null);
                        if (typeof(IUnpackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).GetIsValueType())
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloca(target);
                            }
                            else
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloc(target);
                            }
                            unpackFromMethodILGenerator.EmitAnyLdarg(1);
                            unpackFromMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single <MethodInfo>());
                        }
                        else
                        {
                            EmittingSerializerBuilder <TObject> .EmitUnpackMembers(emitter, unpackFromMethodILGenerator, entries, target);
                        }
                        unpackFromMethodILGenerator.EmitAnyLdloc(target);
                        unpackFromMethodILGenerator.EmitRet();
                    }
                    finally
                    {
                        unpackFromMethodILGenerator.FlushTrace();
                    }
                    serializer = emitter.CreateInstance <TObject>(base.Context);
                }
                finally
                {
                    emitter.FlushTrace();
                }
            }
            return(serializer);
        }