/// <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(); }
private static void EmitWrapperInvocation( ServiceInvokerEmitter emitter, TracingILGenerator il, LocalBuilder service, MethodInfo targetOperation, LocalBuilder[] unpackedArguments ) { /* * returnValue = Task.Factory.StartNew( this.PrivateInvokeCore( state as Tuple<...> ), new Tuple<...>(...) ); */ var itemTypes = Enumerable.Repeat( service, 1 ).Concat( unpackedArguments ).Select( item => item.LocalType ).ToArray(); var tupleTypes = TupleItems.CreateTupleTypeList( itemTypes ); EmitPrivateInvoke( emitter.GetPrivateInvokeMethodILGenerator( targetOperation.ReturnType ), targetOperation, tupleTypes, itemTypes ); il.EmitGetProperty( _taskFactoryProperty ); // new DELEGATE( PrivateInvoke ) ->new DELGATE( null, funcof( PrivateInvoke ) ) il.EmitLdarg_0(); il.EmitLdftn( emitter.PrivateInvokeMethod ); il.EmitNewobj( targetOperation.ReturnType == typeof( void ) ? typeof( Action<object> ).GetConstructor( _delegateConstructorParameterTypes ) : typeof( Func<,> ).MakeGenericType( typeof( object ), targetOperation.ReturnType ).GetConstructor( _delegateConstructorParameterTypes ) ); il.EmitAnyLdloc( service ); foreach ( var item in unpackedArguments ) { il.EmitAnyLdloc( item ); } foreach ( var tupleType in tupleTypes ) { il.EmitNewobj( tupleType.GetConstructors().Single() ); } if ( targetOperation.ReturnType == typeof( void ) ) { il.EmitAnyCall( _taskFactoryStartNew_Action_1_Object_Object ); } else { il.EmitAnyCall( _taskFactoryStartNew_Func_1_Object_T_Object.MakeGenericMethod( targetOperation.ReturnType ) ); } }