File: WorkflowRuntime.cs
Project: ndp\cdf\src\WF\RunTime\System.Workflow.Runtime.csproj (System.Workflow.Runtime)
#region Imports
 
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Reflection;
using System.Threading;
using System.Globalization;
using System.IO;
using System.Workflow.Runtime.Hosting;
using System.Workflow.Runtime.Configuration;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime.Tracking;
using System.Workflow.ComponentModel.Compiler;
using System.Xml;
using System.Workflow.Runtime.DebugEngine;
using System.Workflow.ComponentModel.Serialization;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
 
#endregion
 
namespace System.Workflow.Runtime
{
    #region Class WorkflowRuntimeEventArgs
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WorkflowRuntimeEventArgs : EventArgs
    {
        private bool _isStarted;
 
        internal WorkflowRuntimeEventArgs(bool isStarted)
        {
            _isStarted = isStarted;
        }
 
        public bool IsStarted { get { return _isStarted; } }
    }
 
    #endregion
 
    internal class FanOutOnKeyDictionary<K, V> : IEnumerable<Dictionary<K, V>>
    {
        Dictionary<int, Dictionary<K, V>> dictionaryDictionary;
 
        public FanOutOnKeyDictionary(int fanDegree)
        {
            dictionaryDictionary = new Dictionary<int, Dictionary<K, V>>(fanDegree);
            for (int i = 0; i < fanDegree; ++i)
            {
                dictionaryDictionary.Add(i, new Dictionary<K, V>());
            }
        }
 
        public Dictionary<K, V> this[K key]
        {
            get
            {
                return dictionaryDictionary[Math.Abs(key.GetHashCode() % dictionaryDictionary.Count)];
            }
        }
 
        public bool SafeTryGetValue(K key, out V value)
        {
            Dictionary<K, V> dict = this[key];
            lock (dict)
            {
                return dict.TryGetValue(key, out value);
            }
        }
 
        #region IEnumerable<Dictionary<K,V>> Members
 
        public IEnumerator<Dictionary<K, V>> GetEnumerator()
        {
            return dictionaryDictionary.Values.GetEnumerator();
        }
 
        #endregion
 
        #region IEnumerable Members
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return dictionaryDictionary.Values.GetEnumerator();
        }
 
        #endregion
    }
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public class WorkflowRuntime : IServiceProvider, IDisposable
    {
        #region Private members
 
        internal const string DefaultName = "WorkflowRuntime";
        // Instances aggregation
        private FanOutOnKeyDictionary<Guid, WorkflowExecutor> workflowExecutors;
        private WorkflowDefinitionDispenser _workflowDefinitionDispenser;
 
        private PerformanceCounterManager _performanceCounterManager;
 
        private bool _disposed = false;
        //This is Instance Specific Flag to mark the given instance of
        //Instance Service is started or not.
        private bool isInstanceStarted;
        private DebugController debugController;
        private object _servicesLock = new object();        // protects integrity or the services collection
        private object _startStopLock = new object();       // serializes calls to start and stop        
        private Guid _uid = Guid.NewGuid();
 
        private BooleanSwitch disableWorkflowDebugging = new BooleanSwitch("DisableWorkflowDebugging", "Disables workflow debugging in host");
 
        private TrackingListenerFactory _trackingFactory = new TrackingListenerFactory();
        private static Dictionary<Guid, WeakReference> _runtimes = new Dictionary<Guid, WeakReference>();
        private static object _runtimesLock = new object(); // protects the collection of runtime objects
 
        #endregion
 
        #region Constructors and Configure methods
 
        static WorkflowRuntime()
        {
            // listen to activity definition resolve events
            Activity.ActivityResolve += OnActivityDefinitionResolve;
            Activity.WorkflowChangeActionsResolve += OnWorkflowChangeActionsResolve;
            
            try
            {
                using (TelemetryEventSource eventSource = new TelemetryEventSource())
                {
                    eventSource.V1Runtime();
                }
            }
            catch
            {
            }
        }
 
        public WorkflowRuntime()
        {
            this.PrivateInitialize(null);
        }
 
        public WorkflowRuntime(string configSectionName)
        {
            if (configSectionName == null)
                throw new ArgumentNullException("configSectionName");
 
            WorkflowRuntimeSection settings = ConfigurationManager.GetSection(configSectionName) as WorkflowRuntimeSection;
            if (settings == null)
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                    ExecutionStringManager.ConfigurationSectionNotFound, configSectionName), "configSectionName");
 
            this.PrivateInitialize(settings);
        }
        /// <summary> Creates a WorkflowRuntime from settings. </summary>
        /// <param name="configuration"> The settings for this container </param>
        public WorkflowRuntime(WorkflowRuntimeSection settings)
        {
            if (settings == null)
                throw new ArgumentNullException("settings");
 
            this.PrivateInitialize(settings);
 
        }
 
        private void VerifyInternalState()
        {
            if (_disposed)
                throw new ObjectDisposedException("WorkflowRuntime");
        }
        /// <summary>Initializes this container with the provided settings.</summary>
        /// <param name="settings"></param>
        private void PrivateInitialize(WorkflowRuntimeSection settings)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Created WorkflowRuntime {0}", _uid);
 
            _workflowDefinitionDispenser = new WorkflowDefinitionDispenser(this, (settings != null) ? settings.ValidateOnCreate : true, (settings != null) ? settings.WorkflowDefinitionCacheCapacity : 0);
            workflowExecutors = new FanOutOnKeyDictionary<Guid, WorkflowExecutor>((Environment.ProcessorCount * 4) - 1);
            _name = DefaultName;
 
            if (settings == null || settings.EnablePerformanceCounters) // on by default
                this.PerformanceCounterManager = new PerformanceCounterManager();
 
            if (settings != null)
            {
                _name = settings.Name;
                _configurationParameters = settings.CommonParameters;
 
                foreach (WorkflowRuntimeServiceElement service in settings.Services)
                {
                    AddServiceFromSettings(service);
                }
            }
 
            // create controller
            if (!disableWorkflowDebugging.Enabled)
            {
                DebugController.InitializeProcessSecurity();
                this.debugController = new DebugController(this, _name);
            }
 
            lock (_runtimesLock)
            {
                if (!_runtimes.ContainsKey(_uid))
                    _runtimes.Add(_uid, new WeakReference(this));
            }
        }
 
        public void Dispose()
        {
            lock (_startStopLock)
            {
                if (!_disposed)
                {
                    if (this.debugController != null)
                    {
                        this.debugController.Close();
                    }
                    _workflowDefinitionDispenser.Dispose();
                    _startedServices = false;
                    _disposed = true;
                }
            }
            lock (_runtimesLock)
            {
                //
                // Clean up our weakref entries
                if (_runtimes.ContainsKey(_uid))
                    _runtimes.Remove(_uid);
            }
        }
 
        internal bool IsZombie
        {
            get
            {
                return this._disposed;
            }
        }
 
        #endregion
 
        #region Workflow accessor methods
 
        public WorkflowInstance GetWorkflow(Guid instanceId)
        {
            if (instanceId == Guid.Empty)
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.CantBeEmptyGuid, "instanceId"));
            VerifyInternalState();
            if (!IsStarted)
                throw new InvalidOperationException(ExecutionStringManager.WorkflowRuntimeNotStarted);
 
            WorkflowExecutor executor = Load(instanceId, null, null);
            return executor.WorkflowInstance;
        }
 
        public ReadOnlyCollection<WorkflowInstance> GetLoadedWorkflows()
        {
            VerifyInternalState();
            List<WorkflowInstance> lSchedules = new List<WorkflowInstance>();
            foreach (WorkflowExecutor executor in GetWorkflowExecutors())
            {
                lSchedules.Add(executor.WorkflowInstance);
            }
            return lSchedules.AsReadOnly();
        }
 
        internal WorkflowDefinitionDispenser DefinitionDispenser
        {
            get
            {
                return _workflowDefinitionDispenser;
            }
        }
 
        #endregion
 
        #region Service accessors
 
        internal List<TrackingService> TrackingServices
        {
            get
            {
                List<TrackingService> retval = new List<TrackingService>();
                foreach (TrackingService trackingService in GetAllServices(typeof(TrackingService)))
                {
                    retval.Add(trackingService);
                }
                return retval;
            }
        }
        internal WorkflowSchedulerService SchedulerService
        {
            get
            {
                return GetService<WorkflowSchedulerService>();
            }
        }
 
        internal WorkflowCommitWorkBatchService TransactionService
        {
            get
            {
                return (WorkflowCommitWorkBatchService)GetService(typeof(WorkflowCommitWorkBatchService));
            }
        }
 
        internal WorkflowPersistenceService WorkflowPersistenceService
        {
            get
            {
                return (WorkflowPersistenceService)GetService(typeof(WorkflowPersistenceService));
            }
        }
 
        internal System.Workflow.Runtime.PerformanceCounterManager PerformanceCounterManager
        {
            get
            {
                return _performanceCounterManager;
            }
            private set
            {
                _performanceCounterManager = value;
            }
        }
 
        internal TrackingListenerFactory TrackingListenerFactory
        {
            get
            {
                return _trackingFactory;
            }
        }
 
        #endregion
 
        #region Workflow creation methods
 
        internal Activity GetWorkflowDefinition(Type workflowType)
        {
            if (workflowType == null)
                throw new ArgumentNullException("workflowType");
            VerifyInternalState();
 
            return _workflowDefinitionDispenser.GetRootActivity(workflowType, false, true);
        }
 
        public WorkflowInstance CreateWorkflow(Type workflowType)
        {
            if (workflowType == null)
                throw new ArgumentNullException("workflowType");
            if (!typeof(Activity).IsAssignableFrom(workflowType))
                throw new ArgumentException(ExecutionStringManager.TypeMustImplementRootActivity, "workflowType");
            VerifyInternalState();
 
            return InternalCreateWorkflow(new CreationContext(workflowType, null, null, null), Guid.NewGuid());
        }
 
        public WorkflowInstance CreateWorkflow(Type workflowType, Dictionary<string, object> namedArgumentValues)
        {
            return CreateWorkflow(workflowType, namedArgumentValues, Guid.NewGuid());
        }
 
        public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader)
        {
            if (workflowDefinitionReader == null)
                throw new ArgumentNullException("workflowDefinitionReader");
            VerifyInternalState();
 
            return CreateWorkflow(workflowDefinitionReader, null, null);
        }
 
        public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary<string, object> namedArgumentValues)
        {
            return CreateWorkflow(workflowDefinitionReader, rulesReader, namedArgumentValues, Guid.NewGuid());
        }
 
        public WorkflowInstance CreateWorkflow(Type workflowType, Dictionary<string, object> namedArgumentValues, Guid instanceId)
        {
            if (workflowType == null)
                throw new ArgumentNullException("workflowType");
            if (!typeof(Activity).IsAssignableFrom(workflowType))
                throw new ArgumentException(ExecutionStringManager.TypeMustImplementRootActivity, "workflowType");
            VerifyInternalState();
 
            return InternalCreateWorkflow(new CreationContext(workflowType, null, null, namedArgumentValues), instanceId);
        }
 
        public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary<string, object> namedArgumentValues, Guid instanceId)
        {
            if (workflowDefinitionReader == null)
                throw new ArgumentNullException("workflowDefinitionReader");
            VerifyInternalState();
 
            CreationContext context = new CreationContext(workflowDefinitionReader, rulesReader, namedArgumentValues);
            return InternalCreateWorkflow(context, instanceId);
        }
 
        internal WorkflowInstance InternalCreateWorkflow(CreationContext context, Guid instanceId)
        {
            using (new WorkflowTraceTransfer(instanceId))
            {
                VerifyInternalState();
 
                if (!IsStarted)
                    this.StartRuntime();
 
                WorkflowExecutor executor = GetWorkflowExecutor(instanceId, context);
                if (!context.Created)
                {
                    throw new InvalidOperationException(ExecutionStringManager.WorkflowWithIdAlreadyExists);
                }
 
 
                return executor.WorkflowInstance;
            }
        }
 
        internal sealed class WorkflowExecutorInitializingEventArgs : EventArgs
        {
            private bool _loading = false;
 
            internal WorkflowExecutorInitializingEventArgs(bool loading)
            {
                _loading = loading;
            }
 
            internal bool Loading
            {
                get { return _loading; }
            }
        }
 
        // register for idle events here
        /// <summary>
        /// Raised whenever a WorkflowExecutor is constructed.  This signals either a new instance 
        /// or a loading (args) and gives listening components a chance to set up subscriptions.
        /// </summary>
        internal event EventHandler<WorkflowExecutorInitializingEventArgs> WorkflowExecutorInitializing;
        public event EventHandler<WorkflowEventArgs> WorkflowIdled;
        public event EventHandler<WorkflowEventArgs> WorkflowCreated;
        public event EventHandler<WorkflowEventArgs> WorkflowStarted;
        public event EventHandler<WorkflowEventArgs> WorkflowLoaded;
        public event EventHandler<WorkflowEventArgs> WorkflowUnloaded;
        public event EventHandler<WorkflowCompletedEventArgs> WorkflowCompleted;
        public event EventHandler<WorkflowTerminatedEventArgs> WorkflowTerminated;
        public event EventHandler<WorkflowEventArgs> WorkflowAborted;
        public event EventHandler<WorkflowSuspendedEventArgs> WorkflowSuspended;
        public event EventHandler<WorkflowEventArgs> WorkflowPersisted;
        public event EventHandler<WorkflowEventArgs> WorkflowResumed;
        internal event EventHandler<WorkflowEventArgs> WorkflowDynamicallyChanged;
        public event EventHandler<ServicesExceptionNotHandledEventArgs> ServicesExceptionNotHandled;
        public event EventHandler<WorkflowRuntimeEventArgs> Stopped;
        public event EventHandler<WorkflowRuntimeEventArgs> Started;
 
        internal WorkflowExecutor Load(WorkflowInstance instance)
        {
            return Load(instance.InstanceId, null, instance);
        }
 
        internal WorkflowExecutor Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
        {
            WorkflowExecutor executor;
            Dictionary<Guid, WorkflowExecutor> executors = workflowExecutors[key];
 
 
            lock (executors)
            {
                if (!IsStarted)
                    throw new InvalidOperationException(ExecutionStringManager.WorkflowRuntimeNotStarted);
 
                if (executors.TryGetValue(key, out executor))
                {
                    if (executor.IsInstanceValid)
                    {
                        return executor;
                    }
                }
 
                // If we get here, 'executor' is either null or unusable.
                // Before grabbing the lock, allocate a resource as we
                // may need to insert a new resource.
                executor = new WorkflowExecutor(key);
                if (workflowInstance == null)
                    workflowInstance = new WorkflowInstance(key, this);
 
                InitializeExecutor(key, context, executor, workflowInstance);
                try
                {
                    // If we get here, 'executor' is either null or has not been replaced.
                    // If it has not been replaced, we know that it is unusable
 
                    WorkflowTrace.Host.TraceInformation("WorkflowRuntime:: replacing unusable executor for key {0} with new one (hc: {1})", key, executor.GetHashCode());
                    executors[key] = executor;
                    RegisterExecutor(context != null && context.IsActivation, executor);
                }
                catch
                {
                    WorkflowExecutor currentRes;
                    if (executors.TryGetValue(key, out currentRes))
                    {
                        if (Object.Equals(executor, currentRes))
                        {
                            executors.Remove(key);
                        }
                    }
                    throw;
                }
            }
            executor.Registered(context != null && context.IsActivation);
            return executor;
        }
 
        // this should be called under scheduler lock
        // todo assert this condition
        internal void ReplaceWorkflowExecutor(Guid instanceId, WorkflowExecutor oldWorkflowExecutor, WorkflowExecutor newWorkflowExecutor)
        {
            Dictionary<Guid, WorkflowExecutor> executors = workflowExecutors[instanceId];
            lock (executors)
            {
                oldWorkflowExecutor.IsInstanceValid = false;
 
                WorkflowTrace.Host.TraceInformation("WorkflowRuntime:: replacing old executor for key {0} with new one", instanceId);
                executors[instanceId] = newWorkflowExecutor;
            }
        }
 
        private Activity InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)
        {
            Activity rootActivity = null;
            if (context != null && context.IsActivation)
            {
                Activity workflowDefinition = null;
                string xomlText = null;
                string rulesText = null;
 
                if (context.Type != null)
                {
                    workflowDefinition = _workflowDefinitionDispenser.GetRootActivity(context.Type, false, true);
                    //spawn a new instance
                    rootActivity = _workflowDefinitionDispenser.GetRootActivity(context.Type, true, false);
                }
                else if (context.XomlReader != null)
                {
                    try
                    {
                        context.XomlReader.MoveToContent();
                        while (!context.XomlReader.EOF && !context.XomlReader.IsStartElement())
                            context.XomlReader.Read();
 
                        xomlText = context.XomlReader.ReadOuterXml();
 
                        if (context.RulesReader != null)
                        {
                            context.RulesReader.MoveToContent();
                            while (!context.RulesReader.EOF && !context.RulesReader.IsStartElement())
                                context.RulesReader.Read();
 
                            rulesText = context.RulesReader.ReadOuterXml();
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ArgumentException(ExecutionStringManager.InvalidXAML, e);
                    }
 
                    if (!string.IsNullOrEmpty(xomlText))
                    {
                        workflowDefinition = _workflowDefinitionDispenser.GetRootActivity(xomlText, rulesText, false, true);
                        //spawn a new instance
                        rootActivity = _workflowDefinitionDispenser.GetRootActivity(xomlText, rulesText, true, false);
                    }
                    else
                        throw new ArgumentException(ExecutionStringManager.InvalidXAML);
                }
                rootActivity.SetValue(Activity.WorkflowDefinitionProperty, workflowDefinition);
 
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "Creating instance " + instanceId.ToString());
 
                context.Created = true;
                executor.Initialize(rootActivity, context.InvokerExecutor, context.InvokeActivityID, instanceId, context.Args, workflowInstance);
            }
            else
            {
                if (this.WorkflowPersistenceService == null)
                {
                    string errMsg = String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.MissingPersistenceService, instanceId);
                    WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0, errMsg);
                    throw new InvalidOperationException(errMsg);
                }
 
                // get the state from the persistenceService
                using (RuntimeEnvironment runtimeEnv = new RuntimeEnvironment(this))
                {
                    rootActivity = this.WorkflowPersistenceService.LoadWorkflowInstanceState(instanceId);
                }
                if (rootActivity == null)
                {
                    throw new InvalidOperationException(string.Format(Thread.CurrentThread.CurrentCulture, ExecutionStringManager.InstanceNotFound, instanceId));
                }
                executor.Reload(rootActivity, workflowInstance);
            }
            return rootActivity;
        }
 
        private void RegisterExecutor(bool isActivation, WorkflowExecutor executor)
        {
            if (isActivation)
            {
                executor.RegisterWithRuntime(this);
            }
            else
            {
                executor.ReRegisterWithRuntime(this);
            }
        }
 
        /// <summary>
        /// On receipt of this call unload the instance
        /// This will be invoked by the runtime executor
        /// </summary>
        /// <param name="instanceId"></param>
        internal void OnIdle(WorkflowExecutor executor)
        {
            // raise the OnIdle event , typically handled 
            // by the hosting environment
            try
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "Received OnIdle Event for instance, {0}", executor.InstanceId);
                WorkflowInstance scheduleInstance = executor.WorkflowInstance;
                if (WorkflowIdled != null)
                {
                    WorkflowIdled(this, new WorkflowEventArgs(scheduleInstance));
                }
            }
            catch (Exception)
            {
                //
                WorkflowTrace.Host.TraceEvent(TraceEventType.Warning, 0, "OnIdle Event for instance, {0} threw an exception", executor.InstanceId);
                throw;
            }
        }
 
        private void _unRegister(WorkflowExecutor executor)
        {
            TryRemoveWorkflowExecutor(executor.InstanceId, executor);
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime::_removeInstance, instance:{0}, hc:{1}", executor.InstanceId, executor.GetHashCode());
 
            // be sure to flush all traces
            WorkflowTrace.Runtime.Flush();
            WorkflowTrace.Tracking.Flush();
            WorkflowTrace.Host.Flush();
        }
 
        private WorkflowExecutor GetWorkflowExecutor(Guid instanceId, CreationContext context)
        {
            try
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime dispensing resource, instanceId: {0}", instanceId);
 
                WorkflowExecutor executor = this.Load(instanceId, context, null);
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime dispensing resource instanceId: {0}, hc: {1}", instanceId, executor.GetHashCode());
                return executor;
            }
            catch (OutOfMemoryException)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime dispensing resource, can't create service due to OOM!(1), instance, {0}", instanceId);
                throw;
            }
            catch (Exception e)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime dispensing resource, can't create service due to unexpected exception!(2), instance, {0}, exception, {1}", instanceId, e);
                throw;
            }
        }
 
        #endregion
 
        #region Workflow event handlers
 
        internal void OnScheduleCompleted(WorkflowExecutor schedule, WorkflowCompletedEventArgs args)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleCompleted event raised for instance Id {0}", schedule.InstanceId);
 
            Debug.Assert(schedule != null);
            try
            {
                //Notify Subscribers
                if (WorkflowCompleted != null) WorkflowCompleted(this, args);
            }
            catch (Exception)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime:OnScheduleCompleted Event threw an exception.");
                throw;
            }
            finally
            {
                _unRegister(schedule);
            }
        }
 
        internal void OnScheduleSuspended(WorkflowExecutor schedule, WorkflowSuspendedEventArgs args)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleSuspension event raised for instance Id {0}", schedule.InstanceId);
 
            try
            {
                if (WorkflowSuspended != null) WorkflowSuspended(this, args);
            }
            catch (Exception)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime:OnScheduleSuspended Event threw an exception.");
                throw;
            }
        }
 
        internal void OnScheduleTerminated(WorkflowExecutor schedule, WorkflowTerminatedEventArgs args)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleTermination event raised for instance Id {0}", schedule.InstanceId);
 
            try
            {
                if (WorkflowTerminated != null) WorkflowTerminated(this, args);
            }
            catch (Exception)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime:OnScheduleTerminated Event threw an exception.");
                throw;
            }
            finally
            {
                _unRegister(schedule);
            }
        }
 
        internal void OnScheduleLoaded(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleLoaded event raised for instance Id {0}", schedule.InstanceId);
 
            _OnServiceEvent(schedule, false, WorkflowLoaded);
        }
 
        internal void OnScheduleAborted(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleAborted event raised for instance Id {0}", schedule.InstanceId);
            _OnServiceEvent(schedule, true, WorkflowAborted);
        }
 
        internal void OnScheduleUnloaded(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleUnloaded event raised for instance Id {0}", schedule.InstanceId);
 
            _OnServiceEvent(schedule, true, WorkflowUnloaded);
        }
 
        internal void OnScheduleResumed(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleResumed event raised for instance Id {0}", schedule.InstanceId);
            _OnServiceEvent(schedule, false, WorkflowResumed);
        }
 
        internal void OnScheduleDynamicallyChanged(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:ScheduleDynamicallyChanged event raised for instance Id {0}", schedule.InstanceId);
            _OnServiceEvent(schedule, false, WorkflowDynamicallyChanged);
        }
 
        internal void OnSchedulePersisted(WorkflowExecutor schedule)
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime:SchedulePersisted event raised for instance Id {0}", schedule.InstanceId);
 
            _OnServiceEvent(schedule, false, WorkflowPersisted);
        }
 
        private void _OnServiceEvent(WorkflowExecutor sched, bool unregister, EventHandler<WorkflowEventArgs> handler)
        {
            Debug.Assert(sched != null);
            try
            {
                WorkflowEventArgs args = new WorkflowEventArgs(sched.WorkflowInstance);
                //Notify Subscribers
                if (handler != null) handler(this, args);
            }
            catch (Exception)
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime:OnService Event threw an exception.");
                throw;
            }
            finally
            {
                if (unregister)
                {
                    _unRegister(sched);
                }
            }
        }
 
        internal void RaiseServicesExceptionNotHandledEvent(Exception exception, Guid instanceId)
        {
            VerifyInternalState();
            WorkflowTrace.Host.TraceEvent(TraceEventType.Critical, 0, "WorkflowRuntime:ServicesExceptionNotHandled event raised for instance Id {0} {1}", instanceId, exception.ToString());
            EventHandler<ServicesExceptionNotHandledEventArgs> handler = ServicesExceptionNotHandled;
            if (handler != null)
                handler(this, new ServicesExceptionNotHandledEventArgs(exception, instanceId));
        }
 
        #endregion
 
        #region More service accessors
 
        private Dictionary<Type, List<object>> _services = new Dictionary<Type, List<object>>();
        private string _name;
        private bool _startedServices;
        private NameValueConfigurationCollection _configurationParameters;
        private Dictionary<string, Type> _trackingServiceReplacement;
 
 
        /// <summary> The name of this container. </summary>
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                lock (_startStopLock)
                {
                    if (_startedServices)
                        throw new InvalidOperationException(ExecutionStringManager.CantChangeNameAfterStart);
                    VerifyInternalState();
                    _name = value;
                }
            }
        }
 
        /// <summary>
        /// Returns the configuration parameters that can be shared by all services
        /// </summary>
        internal NameValueConfigurationCollection CommonParameters
        {
            get
            {
                return _configurationParameters;
            }
        }
 
        // A previous tracking service whose type has the string as its AssemblyQualifiedName
        // will be replaced by the current tracking service of the Type. This dictionary is 
        // neede in order to replace the previous tracking service used by a persisted workflow
        // because what is persisted is the one-way hashed string of that AssemblyQualifiedName.
        internal Dictionary<string, Type> TrackingServiceReplacement
        {
            get
            {
                return _trackingServiceReplacement;
            }
        }
 
 
        /// <summary> Adds a service to this container. </summary>
        /// <param name="service"> The service to add </param>
        /// <exception cref="InvalidOperationException"/>
        public void AddService(object service)
        {
            if (service == null)
                throw new ArgumentNullException("service");
            VerifyInternalState();
 
            using (new WorkflowRuntime.EventContext())
            {
                lock (_startStopLock)
                {
                    AddServiceImpl(service);
                }
            }
        }
 
        private void AddServiceImpl(object service)
        {
            //ASSERT: _startStopLock is held
 
            lock (_servicesLock)
            {
                if (GetAllServices(service.GetType()).Contains(service))
                    throw new InvalidOperationException(ExecutionStringManager.CantAddServiceTwice);
 
                if (_startedServices && IsCoreService(service))
                    throw new InvalidOperationException(ExecutionStringManager.CantChangeImmutableContainer);
 
                Type basetype = service.GetType();
                if (basetype.IsSubclassOf(typeof(TrackingService)))
                {
                    AddTrackingServiceReplacementInfo(basetype);
                }
 
 
                foreach (Type t in basetype.GetInterfaces())
                {
                    List<object> al;
                    if (_services.ContainsKey(t))
                    {
                        al = _services[t];
                    }
                    else
                    {
                        al = new List<object>();
                        _services.Add(t, al);
                    }
                    al.Add(service);
                }
 
                while (basetype != null)
                {
                    List<object> al = null;
                    if (_services.ContainsKey(basetype))
                    {
                        al = _services[basetype];
                    }
                    else
                    {
                        al = new List<object>();
                        _services.Add(basetype, al);
                    }
                    al.Add(service);
                    basetype = basetype.BaseType;
                }
            }
 
            WorkflowRuntimeService wrs = service as WorkflowRuntimeService;
            if (wrs != null)
            {
                wrs.SetRuntime(this);
                if (_startedServices)
                    wrs.Start();
            }
        }
 
 
        /// <summary> Removes a service. </summary>
        /// <param name="service"> The service to remove </param>
        public void RemoveService(object service)
        {
            if (service == null)
                throw new ArgumentNullException("service");
            VerifyInternalState();
 
            using (new WorkflowRuntime.EventContext())
            {
                lock (_startStopLock)
                {
                    lock (_servicesLock)
                    {
                        if (_startedServices && IsCoreService(service))
                            throw new InvalidOperationException(ExecutionStringManager.CantChangeImmutableContainer);
 
                        if (!GetAllServices(service.GetType()).Contains(service))
                            throw new InvalidOperationException(ExecutionStringManager.CantRemoveServiceNotContained);
 
                        Type type = service.GetType();
                        if (type.IsSubclassOf(typeof(TrackingService)))
                        {
                            RemoveTrackingServiceReplacementInfo(type);
                        }
 
                        foreach (List<object> al in _services.Values)
                        {
                            if (al.Contains(service))
                            {
                                al.Remove(service);
                            }
                        }
                    }
                    WorkflowRuntimeService wrs = service as WorkflowRuntimeService;
                    if (wrs != null)
                    {
                        if (_startedServices)
                            wrs.Stop();
 
                        wrs.SetRuntime(null);
                    }
                }
            }
        }
 
        private void AddTrackingServiceReplacementInfo(Type type)
        {
            Debug.Assert(type.IsSubclassOf(typeof(TrackingService)), "Argument should be a subtype of TrackingService");
            object[] attributes = type.GetCustomAttributes(typeof(PreviousTrackingServiceAttribute), true);
            if (attributes != null && attributes.Length > 0)
            {
                foreach (object attribute in attributes)
                {
                    if (_trackingServiceReplacement == null)
                    {
                        _trackingServiceReplacement = new Dictionary<string, Type>();
                    }
                    _trackingServiceReplacement.Add(((PreviousTrackingServiceAttribute)attribute).AssemblyQualifiedName, type);
                }
            }
        }
 
        private void RemoveTrackingServiceReplacementInfo(Type type)
        {
            Debug.Assert(type.IsSubclassOf(typeof(TrackingService)), "Argument should be a subtype of TrackingService");
            object[] attributes = type.GetCustomAttributes(typeof(PreviousTrackingServiceAttribute), true);
            if (attributes != null && attributes.Length > 0)
            {
                foreach (object attribute in attributes)
                {
                    string previousTrackingService = ((PreviousTrackingServiceAttribute)attribute).AssemblyQualifiedName;
                    if (_trackingServiceReplacement.ContainsKey(previousTrackingService))
                    {
                        _trackingServiceReplacement.Remove(previousTrackingService);
                    }
                }
            }
        }
 
        private bool IsCoreService(object service)
        {
            return service is WorkflowSchedulerService
                || service is WorkflowPersistenceService
                || service is TrackingService
                || service is WorkflowCommitWorkBatchService
                || service is WorkflowLoaderService;
        }
 
 
        /// <summary> Returns a collection of all services that implement the give type. </summary>
        /// <param name="serviceType"> The type to look for </param>
        /// <returns> A collection of zero or more services </returns>
        public ReadOnlyCollection<object> GetAllServices(Type serviceType)
        {
            if (serviceType == null)
                throw new ArgumentNullException("serviceType");
            VerifyInternalState();
 
            lock (_servicesLock)
            {
                List<object> retval = new List<object>();
                if (_services.ContainsKey(serviceType))
                    retval.AddRange(_services[serviceType]);
 
                return new ReadOnlyCollection<object>(retval);
            }
        }
 
 
        public T GetService<T>()
        {
            VerifyInternalState();
            return (T)GetService(typeof(T));
        }
 
        public ReadOnlyCollection<T> GetAllServices<T>()
        {
            VerifyInternalState();
            List<T> l = new List<T>();
            foreach (T t in GetAllServices(typeof(T)))
                l.Add(t);
            return new ReadOnlyCollection<T>(l);
        }
 
        /// <summary> Looks for a service of the given type. </summary>
        /// <param name="serviceType"> The type of object to find </param>
        /// <returns> An object of the requested type, or null</returns>
        public object GetService(Type serviceType)
        {
            if (serviceType == null)
                throw new ArgumentNullException("serviceType");
            VerifyInternalState();
 
            lock (_servicesLock)
            {
                object retval = null;
 
                if (_services.ContainsKey(serviceType))
                {
                    List<object> al = _services[serviceType];
 
                    if (al.Count > 1)
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                            ExecutionStringManager.MoreThanOneService, serviceType.ToString()));
 
                    if (al.Count == 1)
                        retval = al[0];
                }
 
                return retval;
            }
        }
 
        #endregion
 
        #region Other methods
 
 
        /// <summary> Raises the Starting event </summary>
        /// <remarks>
        /// </remarks>
        public void StartRuntime()
        {
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Starting WorkflowRuntime {0}", _uid);
            lock (_startStopLock)
            {
                VerifyInternalState();
 
                if (!_startedServices)
                {
 
                    if (GetAllServices(typeof(WorkflowCommitWorkBatchService)).Count == 0)
                        AddServiceImpl(new DefaultWorkflowCommitWorkBatchService());
 
                    if (GetAllServices(typeof(WorkflowSchedulerService)).Count == 0)
                        AddServiceImpl(new DefaultWorkflowSchedulerService());
 
                    if (GetAllServices(typeof(WorkflowLoaderService)).Count == 0)
                        AddServiceImpl(new DefaultWorkflowLoaderService());
 
                    if (GetAllServices(typeof(WorkflowCommitWorkBatchService)).Count != 1)
                        throw new InvalidOperationException(String.Format(
                        CultureInfo.CurrentCulture,
                        ExecutionStringManager.InvalidWorkflowRuntimeConfiguration,
                        typeof(WorkflowCommitWorkBatchService).Name));
 
                    if (GetAllServices(typeof(WorkflowSchedulerService)).Count != 1)
                        throw new InvalidOperationException(String.Format(
                        CultureInfo.CurrentCulture, ExecutionStringManager.InvalidWorkflowRuntimeConfiguration,
                        typeof(WorkflowSchedulerService).Name));
 
                    if (GetAllServices(typeof(WorkflowLoaderService)).Count != 1)
                        throw new InvalidOperationException(String.Format(
                        CultureInfo.CurrentCulture, ExecutionStringManager.InvalidWorkflowRuntimeConfiguration,
                        typeof(WorkflowLoaderService).Name));
 
                    if (GetAllServices(typeof(WorkflowPersistenceService)).Count > 1)
                        throw new InvalidOperationException(String.Format(
                        CultureInfo.CurrentCulture, ExecutionStringManager.InvalidWorkflowRuntimeConfiguration,
                        typeof(WorkflowPersistenceService).Name));
 
                    if (GetAllServices(typeof(WorkflowTimerService)).Count == 0)
                    {
                        AddServiceImpl(new WorkflowTimerService());
                    }
 
                    //Mark this instance has started
                    isInstanceStarted = true;
 
                    //Set up static tracking structures
                    _trackingFactory.Initialize(this);
                    if (this.PerformanceCounterManager != null)
                    {
                        this.PerformanceCounterManager.Initialize(this);
                        this.PerformanceCounterManager.SetInstanceName(this.Name);
                    }
 
                    foreach (WorkflowRuntimeService s in GetAllServices<WorkflowRuntimeService>())
                    {
                        s.Start();
                    }
 
                    _startedServices = true;
                    using (new WorkflowRuntime.EventContext())
                    {
                        EventHandler<WorkflowRuntimeEventArgs> ss = Started;
                        if (ss != null)
                            ss(this, new WorkflowRuntimeEventArgs(isInstanceStarted));
                    }
                }
            }
            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Started WorkflowRuntime {0}", _uid);
        }
 
        void DynamicUpdateCommit(object sender, WorkflowExecutor.DynamicUpdateEventArgs e)
        {
            if (null == sender)
                throw new ArgumentNullException("sender");
 
            if (!typeof(WorkflowExecutor).IsInstanceOfType(sender))
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidArgumentType, "sender", typeof(WorkflowExecutor).ToString()));
 
            WorkflowExecutor exec = (WorkflowExecutor)sender;
 
            OnScheduleDynamicallyChanged(exec);
        }
 
        internal void WorkflowExecutorCreated(WorkflowExecutor workflowExecutor, bool loaded)
        {
            //
            // Fire the event for all other components that need to register for notification of WorkflowExecutor events
            EventHandler<WorkflowExecutorInitializingEventArgs> localEvent = WorkflowExecutorInitializing;
            if (null != localEvent)
                localEvent(workflowExecutor, new WorkflowExecutorInitializingEventArgs(loaded));
 
            workflowExecutor.WorkflowExecutionEvent += new EventHandler<WorkflowExecutor.WorkflowExecutionEventArgs>(WorkflowExecutionEvent);
        }
 
        void WorkflowExecutionEvent(object sender, WorkflowExecutor.WorkflowExecutionEventArgs e)
        {
            if (null == sender)
                throw new ArgumentNullException("sender");
 
            if (!typeof(WorkflowExecutor).IsInstanceOfType(sender))
                throw new ArgumentException("sender");
 
            WorkflowExecutor exec = (WorkflowExecutor)sender;
 
            switch (e.EventType)
            {
                case WorkflowEventInternal.Idle:
                    OnIdle(exec);
                    break;
                case WorkflowEventInternal.Created:
                    if (WorkflowCreated != null)
                        WorkflowCreated(this, new WorkflowEventArgs(exec.WorkflowInstance));
                    break;
                case WorkflowEventInternal.Started:
                    if (WorkflowStarted != null)
                        WorkflowStarted(this, new WorkflowEventArgs(exec.WorkflowInstance));
                    break;
                case WorkflowEventInternal.Loaded:
                    OnScheduleLoaded(exec);
                    break;
                case WorkflowEventInternal.Unloaded:
                    OnScheduleUnloaded(exec);
                    break;
                case WorkflowEventInternal.Completed:
                    OnScheduleCompleted(exec, CreateCompletedEventArgs(exec));
                    break;
                case WorkflowEventInternal.Terminated:
                    WorkflowExecutor.WorkflowExecutionTerminatedEventArgs args = (WorkflowExecutor.WorkflowExecutionTerminatedEventArgs)e;
 
                    if (null != args.Exception)
                        OnScheduleTerminated(exec, new WorkflowTerminatedEventArgs(exec.WorkflowInstance, args.Exception));
                    else
                        OnScheduleTerminated(exec, new WorkflowTerminatedEventArgs(exec.WorkflowInstance, args.Error));
 
                    break;
                case WorkflowEventInternal.Aborted:
                    OnScheduleAborted(exec);
                    break;
                case WorkflowEventInternal.Suspended:
                    WorkflowExecutor.WorkflowExecutionSuspendedEventArgs sargs = (WorkflowExecutor.WorkflowExecutionSuspendedEventArgs)e;
                    OnScheduleSuspended(exec, new WorkflowSuspendedEventArgs(exec.WorkflowInstance, sargs.Error));
                    break;
                case WorkflowEventInternal.Persisted:
                    OnSchedulePersisted(exec);
                    break;
                case WorkflowEventInternal.Resumed:
                    OnScheduleResumed(exec);
                    break;
                case WorkflowEventInternal.DynamicChangeCommit:
                    DynamicUpdateCommit(exec, (WorkflowExecutor.DynamicUpdateEventArgs)e);
                    break;
                default:
                    break;
            }
        }
 
        private WorkflowCompletedEventArgs CreateCompletedEventArgs(WorkflowExecutor exec)
        {
            WorkflowCompletedEventArgs args = new WorkflowCompletedEventArgs(exec.WorkflowInstance, exec.WorkflowDefinition);
            foreach (PropertyInfo property in _workflowDefinitionDispenser.GetOutputParameters(exec.RootActivity))
                args.OutputParameters.Add(property.Name, property.GetValue(exec.RootActivity, null));
 
            return args;
        }
 
        private void StopServices()
        {
            // Stop remaining services
            foreach (WorkflowRuntimeService s in GetAllServices<WorkflowRuntimeService>())
            {
                s.Stop();
            }
        }
 
        /// <summary> Fires the Stopping event </summary>
        public void StopRuntime()
        {
            VerifyInternalState();
 
            using (new WorkflowRuntime.EventContext())
            {
                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Stopping WorkflowRuntime {0}", _uid);
                lock (_startStopLock)
                {
                    if (_startedServices)
                    {
                        try
                        {
                            isInstanceStarted = false;
 
                            if (this.WorkflowPersistenceService != null)
                            {
                                //
                                // GetWorkflowExecutors() takes a lock on workflowExecutors
                                // and then returns a copy of the list.  As long as GetWorkflowExecutors()
                                // returns a non empty/null list we'll attempt to unload what's in it.
                                IList<WorkflowExecutor> executors = GetWorkflowExecutors();
                                while ((null != executors) && (executors.Count > 0))
                                {
                                    foreach (WorkflowExecutor executor in executors)
                                    {
                                        if (executor.IsInstanceValid)
                                        {
                                            try
                                            {
                                                WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Calling Unload on instance {0} executor hc {1}", executor.InstanceIdString, executor.GetHashCode());
                                                executor.Unload();
                                            }
                                            catch (ExecutorLocksHeldException)
                                            {
                                                //
                                                // This exception means that an atomic scope is ongoing
                                                // (we cannot unload/suspend during an atomic scope)
                                                // This instance will still be in the GetWorkflowExecutors list
                                                // so we'll attempt to unload it on the next outer loop
                                                // Yes, we may loop indefinitely if an atomic tx is hung
                                                // See WorkflowInstance.Unload for an example of retrying
                                                // when this exception is thrown.
                                            }
                                            catch (InvalidOperationException)
                                            {
                                                if (executor.IsInstanceValid)
                                                {
                                                    //
                                                    // Failed to stop, reset the flag
                                                    isInstanceStarted = true;
                                                    throw;
                                                }
                                            }
                                            catch
                                            {
                                                //
                                                // Failed to stop, reset the flag
                                                isInstanceStarted = true;
                                                throw;
                                            }
                                        }
                                    }
                                    //
                                    // Check if anything was added to the main list  
                                    // while we were working on the copy.
                                    // This happens if a executor reverts to a checkpoint.
                                    // There is the potential to loop indefinitely if
                                    // an instance continually reverts.
                                    executors = GetWorkflowExecutors();
                                }
                            }
 
                            StopServices();
                            _startedServices = false;
 
 
                            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime: Stopped WorkflowRuntime {0}", _uid);
 
                            //
                            // Clean up tracking
                            _trackingFactory.Uninitialize(this);
                            if (this.PerformanceCounterManager != null)
                            {
                                this.PerformanceCounterManager.Uninitialize(this);
                            }
 
                            EventHandler<WorkflowRuntimeEventArgs> handler = Stopped;
                            if (handler != null)
                                handler(this, new WorkflowRuntimeEventArgs(isInstanceStarted));
                        }
                        catch (Exception)
                        {
                            WorkflowTrace.Host.TraceEvent(TraceEventType.Error, 0, "WorkflowRuntime::StartUnload Unexpected Exception");
                            throw;
                        }
                        finally
                        {
                            isInstanceStarted = false;
                        }
                    }
                }
            }
        }
 
        /// <summary> True if services have been started and not stopped </summary>
        public bool IsStarted
        {
            get
            {
                return _startedServices;
            }
        }
 
 
        private static Activity OnActivityDefinitionResolve(object sender, ActivityResolveEventArgs e)
        {
            WorkflowRuntime runtime = e.ServiceProvider as WorkflowRuntime;
            if (runtime == null)
                runtime = RuntimeEnvironment.CurrentRuntime;
 
            Debug.Assert(runtime != null);
            if (runtime != null)
            {
                if (e.Type != null)
                    return runtime._workflowDefinitionDispenser.GetRootActivity(e.Type, e.CreateNewDefinition, e.InitializeForRuntime);
                else
                    return runtime._workflowDefinitionDispenser.GetRootActivity(e.WorkflowMarkup, e.RulesMarkup, e.CreateNewDefinition, e.InitializeForRuntime);
            }
            return null;
        }
 
        internal static TypeProvider CreateTypeProvider(Activity rootActivity)
        {
            TypeProvider typeProvider = new TypeProvider(null);
 
            Type companionType = rootActivity.GetType();
            typeProvider.SetLocalAssembly(companionType.Assembly);
            typeProvider.AddAssembly(companionType.Assembly);
 
            foreach (AssemblyName assemblyName in companionType.Assembly.GetReferencedAssemblies())
            {
                Assembly referencedAssembly = null;
                try
                {
                    referencedAssembly = Assembly.Load(assemblyName);
                    if (referencedAssembly != null)
                        typeProvider.AddAssembly(referencedAssembly);
                }
                catch
                {
                }
 
                if (referencedAssembly == null && assemblyName.CodeBase != null)
                    typeProvider.AddAssemblyReference(assemblyName.CodeBase);
            }
 
            return typeProvider;
        }
 
        private static ArrayList OnWorkflowChangeActionsResolve(object sender, WorkflowChangeActionsResolveEventArgs e)
        {
            ArrayList changes = null;
            WorkflowRuntime runtime = RuntimeEnvironment.CurrentRuntime;
            Debug.Assert(runtime != null);
            if (runtime != null)
            {
                WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
                ServiceContainer serviceContainer = new ServiceContainer();
                ITypeProvider typeProvider = runtime.GetService<ITypeProvider>();
                if (typeProvider != null)
                    serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
                else if (sender is Activity)
                {
                    serviceContainer.AddService(typeof(ITypeProvider), CreateTypeProvider(sender as Activity));
                }
 
                DesignerSerializationManager manager = new DesignerSerializationManager(serviceContainer);
                using (manager.CreateSession())
                {
                    using (StringReader reader = new StringReader(e.WorkflowChangesMarkup))
                    {
                        using (XmlReader xmlReader = XmlReader.Create(reader))
                        {
                            WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
                            changes = serializer.Deserialize(xomlSerializationManager, xmlReader) as ArrayList;
                        }
                    }
                }
            }
 
            return changes;
        }
 
        /// <summary> Creates and adds a service to this container. </summary>
        /// <param name="serviceSettings"> Description of the service to add. </param>
        private void AddServiceFromSettings(WorkflowRuntimeServiceElement serviceSettings)
        {
            object service = null;
 
            Type t = Type.GetType(serviceSettings.Type, true);
 
            ConstructorInfo serviceProviderAndSettingsConstructor = null;
            ConstructorInfo serviceProviderConstructor = null;
            ConstructorInfo settingsConstructor = null;
 
            foreach (ConstructorInfo ci in t.GetConstructors())
            {
                ParameterInfo[] pi = ci.GetParameters();
                if (pi.Length == 1)
                {
                    if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType))
                    {
                        serviceProviderConstructor = ci;
                    }
                    else if (typeof(NameValueCollection).IsAssignableFrom(pi[0].ParameterType))
                    {
                        settingsConstructor = ci;
                    }
                }
                else if (pi.Length == 2)
                {
                    if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType)
                        && typeof(NameValueCollection).IsAssignableFrom(pi[1].ParameterType))
                    {
                        serviceProviderAndSettingsConstructor = ci;
                        break;
                    }
                }
            }
 
            if (serviceProviderAndSettingsConstructor != null)
            {
                service = serviceProviderAndSettingsConstructor.Invoke(
                    new object[] { this, serviceSettings.Parameters });
            }
            else if (serviceProviderConstructor != null)
            {
                service = serviceProviderConstructor.Invoke(new object[] { this });
            }
            else if (settingsConstructor != null)
            {
                service = settingsConstructor.Invoke(new object[] { serviceSettings.Parameters });
            }
            else
            {
                service = Activator.CreateInstance(t);
            }
 
            AddServiceImpl(service);
        }
 
        internal static void ClearTrackingProfileCache()
        {
            lock (_runtimesLock)
            {
                foreach (WeakReference wr in _runtimes.Values)
                {
                    WorkflowRuntime runtime = wr.Target as WorkflowRuntime;
                    if (null != runtime)
                    {
                        if ((null != runtime.TrackingListenerFactory) && (null != runtime.TrackingListenerFactory.TrackingProfileManager))
                            runtime.TrackingListenerFactory.TrackingProfileManager.ClearCacheImpl();
                    }
                }
            }
        }
        /// <summary>Utility class that prevents reentrance during event processing.</summary>
        /// <remarks>
        /// When created an EventContext it creates a static variable local to 
        /// a managed thread (similar to the old TLS slot), 
        /// which can detect cases when events are invoked while handling other events. 
        /// The variable is removed on dispose.
        /// </remarks>
        internal sealed class EventContext : IDisposable
        {
 
            /// <summary>
            /// Indicates that the value of a static field is unique for each thread
            /// CLR Perf suggests using this attribute over the slot approach.
            /// </summary>
            [ThreadStatic()]
            static object threadData;
 
            public EventContext(params Object[] ignored)
            {
                if (threadData != null)
                    throw new InvalidOperationException(ExecutionStringManager.CannotCauseEventInEvent);
 
                threadData = this;
            }
 
            void IDisposable.Dispose()
            {
                Debug.Assert(threadData != null, "unexpected call to EventContext::Dispose method");
                threadData = null;
            }
        }
 
        #endregion
 
        #region WorkflowExecutor utility methods
        private IList<WorkflowExecutor> GetWorkflowExecutors()
        {
            //
            // This is a safety check in to avoid returning invalid executors in the following cases:
            // 1.  We ---- between the executor going invalid and getting removed from the list.
            // 2.  We have a leak somewhere where invalid executors are not getting removed from the list.
            List<WorkflowExecutor> executorsList = new List<WorkflowExecutor>();
            foreach (Dictionary<Guid, WorkflowExecutor> executors in workflowExecutors)
            {
                lock (executors)
                {
                    foreach (WorkflowExecutor executor in executors.Values)
                    {
                        if ((null != executor) && (executor.IsInstanceValid))
                            executorsList.Add(executor);
                    }
                }
            }
            return executorsList;
        }
 
        private bool TryRemoveWorkflowExecutor(Guid instanceId, WorkflowExecutor executor)
        {
            Dictionary<Guid, WorkflowExecutor> executors = workflowExecutors[instanceId];
            lock (executors)
            {
                WorkflowExecutor currentRes;
                if (executors.TryGetValue(instanceId, out currentRes) && Object.Equals(executor, currentRes))
                {
                    WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "WorkflowRuntime::TryRemoveWorkflowExecutor, instance:{0}, hc:{1}", executor.InstanceIdString, executor.GetHashCode());
                    return executors.Remove(instanceId);
                }
 
                return false;
            }
        }
        #endregion
    }
}