private async Task EndActiveDialogAsync(DialogReason reason, object result = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (result is CancellationToken)
            {
                throw new ArgumentException($"{nameof(result)} cannot be a cancellation token");
            }

            var instance = ActiveDialog;

            if (instance != null)
            {
                // Lookup dialog
                var dialog = Dialogs.Find(instance.Id);
                if (dialog != null)
                {
                    // Notify dialog of end
                    await this.DebuggerStepAsync(dialog, "EndDialog", cancellationToken).ConfigureAwait(false);

                    await dialog.EndDialogAsync(Context, instance, reason, cancellationToken).ConfigureAwait(false);
                }

                // Pop dialog off stack
                Stack.RemoveAt(0);

                // set Turn.LastResult to result
                ObjectPath.SetPathValue(this.Context.TurnState, TurnPath.LastResult, result);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DialogContext"/> class from the turn context.
        /// </summary>
        /// <param name="dialogs">The dialog set to create the dialog context for.</param>
        /// <param name="turnContext">The current turn context.</param>
        /// <param name="state">The state property from which to retrieve the dialog context.</param>
        public DialogContext(DialogSet dialogs, ITurnContext turnContext, DialogState state)
        {
            Dialogs = dialogs ?? throw new ArgumentNullException(nameof(dialogs));
            Context = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            Stack   = state.DialogStack;

            ObjectPath.SetPathValue(turnContext.TurnState, TurnPath.ACTIVITY, Context.Activity);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DialogContext"/> class from the turn context.
        /// </summary>
        /// <param name="dialogs">The dialog set to create the dialog context for.</param>
        /// <param name="turnContext">The current turn context.</param>
        /// <param name="state">The state property from which to retrieve the dialog context.</param>
        public DialogContext(DialogSet dialogs, ITurnContext turnContext, DialogState state)
        {
            Dialogs  = dialogs ?? throw new ArgumentNullException(nameof(dialogs));
            Context  = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            Stack    = state.DialogStack;
            State    = new DialogStateManager(this);
            Services = new TurnContextStateCollection();

            ObjectPath.SetPathValue(turnContext.TurnState, TurnPath.Activity, Context.Activity);
        }
        /// <summary>
        /// Starts a new dialog and replaces on the stack the currently active dialog with the new one.
        /// This is particularly useful for creating loops or redirecting to another dialog.
        /// </summary>
        /// <param name="dialogId">ID of the new dialog to start.</param>
        /// <param name="options">Optional, information to pass to the dialog being started.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <remarks>If the task is successful, the result indicates whether the dialog is still
        /// active after the turn has been processed by the dialog.</remarks>
        /// <seealso cref="BeginDialogAsync(string, object, CancellationToken)"/>
        /// <seealso cref="EndDialogAsync(object, CancellationToken)"/>
        public async Task <DialogTurnResult> ReplaceDialogAsync(string dialogId, object options = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (options is CancellationToken)
            {
                throw new ArgumentException($"{nameof(options)} cannot be a cancellation token");
            }

            // End the current dialog and giving the reason.
            await EndActiveDialogAsync(DialogReason.ReplaceCalled, cancellationToken : cancellationToken).ConfigureAwait(false);

            ObjectPath.SetPathValue(this.Context.TurnState, "turn.__repeatDialogId", dialogId);

            // Start replacement dialog
            return(await BeginDialogAsync(dialogId, options, cancellationToken).ConfigureAwait(false));
        }