コード例 #1
0
		/// <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();
		}
コード例 #2
0
		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 ) );
			}

		}