/// <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();
        }