File: System\Activities\Debugger\DebugController.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
 
namespace System.Activities.Debugger
{
    using System;
    using System.Activities.Hosting;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq.Expressions;
    using System.Runtime;
    using System.Activities.Validation;
 
    // DebugController, one is needed per ActivityExecutor.
    [DebuggerNonUserCode]
    class DebugController
    {
        WorkflowInstance host;
        DebugManager debugManager;  // Instantiated after first instrumentation is successful.
 
        public DebugController(WorkflowInstance host)
        {
            this.host = host;
        }
       
        public void WorkflowStarted()
        {   
        }
      
        public void WorkflowCompleted()
        {
            if (this.debugManager != null)  
            {
                this.debugManager.Exit();
                this.debugManager = null;
            }
        }
 
        public void ActivityStarted(ActivityInstance activityInstance)
        {
            if (!(activityInstance.Activity.RootActivity is Constraint))  // Don't debug an activity in a Constraint
            {
                EnsureActivityInstrumented(activityInstance, false);
                this.debugManager.OnEnterState(activityInstance);
            }
        }
 
        public void ActivityCompleted(ActivityInstance activityInstance)
        {
            if (!(activityInstance.Activity.RootActivity is Constraint)) // Don't debug an activity in a Constraint
            {
                EnsureActivityInstrumented(activityInstance, true);
                this.debugManager.OnLeaveState(activityInstance);
            }
        }
 
        // Lazy instrumentation.
        // Parameter primeCurrentInstance specify whether priming (if needed) is done
        // up to the current instance.  Set this to true when calling this from an "...Completed" 
        // (exit state).
        void EnsureActivityInstrumented(ActivityInstance instance, bool primeCurrentInstance)
        {          
            if (this.debugManager == null)
            {   // Workflow has not been instrumented yet.
 
                // Finding rootInstance and check all referred sources.
                Stack<ActivityInstance> ancestors = new Stack<ActivityInstance>();
                while (instance.Parent != null)
                {
                    ancestors.Push(instance);
                    instance = instance.Parent;
                }
 
                Activity rootActivity = instance.Activity;
 
                // Do breakOnStartup only if debugger is attached from the beginning, i.e. no priming needed.
                // This specified by change the last parameter below to: "(ancestors.Count == 0)".
                this.debugManager = new DebugManager(rootActivity, "Workflow", "Workflow", "DebuggerThread", false, this.host, ancestors.Count == 0);
 
                if (ancestors.Count > 0)
                {
                    // Priming the background thread 
                    this.debugManager.IsPriming = true;
                    while (ancestors.Count > 0)
                    {
                        ActivityInstance ancestorInstance = ancestors.Pop();
                        this.debugManager.OnEnterState(ancestorInstance);
                    }
                    if (primeCurrentInstance)
                    {
                        this.debugManager.OnEnterState(instance);
                    }
                    this.debugManager.IsPriming = false;
                }
            }
        }
    }
}