Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / RunTime / WorkflowRuntime.cs / 1305376 / WorkflowRuntime.cs
#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
public sealed class WorkflowRuntimeEventArgs : EventArgs
{
private bool _isStarted;
internal WorkflowRuntimeEventArgs(bool isStarted)
{
_isStarted = isStarted;
}
public bool IsStarted { get { return _isStarted; } }
}
#endregion
internal class FanOutOnKeyDictionary: IEnumerable>
{
Dictionary> dictionaryDictionary;
public FanOutOnKeyDictionary( int fanDegree )
{
dictionaryDictionary = new Dictionary>(fanDegree);
for (int i = 0; i < fanDegree; ++i)
{
dictionaryDictionary.Add(i, new Dictionary());
}
}
public Dictionary this[K key]
{
get
{
return dictionaryDictionary[Math.Abs(key.GetHashCode() % dictionaryDictionary.Count)];
}
}
public bool SafeTryGetValue(K key, out V value)
{
Dictionary dict = this[key];
lock (dict)
{
return dict.TryGetValue(key, out value);
}
}
#region IEnumerable> Members
public IEnumerator> GetEnumerator()
{
return dictionaryDictionary.Values.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return dictionaryDictionary.Values.GetEnumerator();
}
#endregion
}
public class WorkflowRuntime : IServiceProvider, IDisposable
{
#region Private members
internal const string DefaultName = "WorkflowRuntime";
// Instances aggregation
private FanOutOnKeyDictionary 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 _runtimes = new Dictionary();
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;
}
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);
}
/// Creates a WorkflowRuntime from settings.
/// The settings for this container
public WorkflowRuntime(WorkflowRuntimeSection settings)
{
if (settings == null)
throw new ArgumentNullException("settings");
this.PrivateInitialize(settings);
}
private void VerifyInternalState()
{
if (_disposed)
throw new ObjectDisposedException("WorkflowRuntime");
}
/// Initializes this container with the provided settings.
///
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((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 GetLoadedWorkflows()
{
VerifyInternalState();
List lSchedules = new List();
foreach (WorkflowExecutor executor in GetWorkflowExecutors())
{
lSchedules.Add(executor.WorkflowInstance);
}
return lSchedules.AsReadOnly();
}
internal WorkflowDefinitionDispenser DefinitionDispenser
{
get
{
return _workflowDefinitionDispenser;
}
}
#endregion
#region Service accessors
internal List TrackingServices
{
get
{
List retval = new List();
foreach (TrackingService trackingService in GetAllServices(typeof(TrackingService)))
{
retval.Add(trackingService);
}
return retval;
}
}
internal WorkflowSchedulerService SchedulerService
{
get
{
return GetService();
}
}
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 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 namedArgumentValues)
{
return CreateWorkflow(workflowDefinitionReader, rulesReader, namedArgumentValues, Guid.NewGuid());
}
public WorkflowInstance CreateWorkflow(Type workflowType, Dictionary 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 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
///
/// 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.
///
internal event EventHandler WorkflowExecutorInitializing;
public event EventHandler WorkflowIdled;
public event EventHandler WorkflowCreated;
public event EventHandler WorkflowStarted;
public event EventHandler WorkflowLoaded;
public event EventHandler WorkflowUnloaded;
public event EventHandler WorkflowCompleted;
public event EventHandler WorkflowTerminated;
public event EventHandler WorkflowAborted;
public event EventHandler WorkflowSuspended;
public event EventHandler WorkflowPersisted;
public event EventHandler WorkflowResumed;
internal event EventHandler WorkflowDynamicallyChanged;
public event EventHandler ServicesExceptionNotHandled;
public event EventHandler Stopped;
public event EventHandler Started;
internal WorkflowExecutor Load(WorkflowInstance instance)
{
return Load(instance.InstanceId, null, instance);
}
internal WorkflowExecutor Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
{
WorkflowExecutor executor;
Dictionary 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 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);
}
}
///
/// On receipt of this call unload the instance
/// This will be invoked by the runtime executor
///
///
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 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} " + exception.ToString(), instanceId);
EventHandler handler = ServicesExceptionNotHandled;
if (handler != null)
handler(this, new ServicesExceptionNotHandledEventArgs(exception, instanceId));
}
#endregion
#region More service accessors
private Dictionary> _services = new Dictionary>();
private string _name;
private bool _startedServices;
private NameValueConfigurationCollection _configurationParameters;
private Dictionary _trackingServiceReplacement;
/// The name of this container.
public string Name
{
get
{
return _name;
}
set
{
lock (_startStopLock)
{
if (_startedServices)
throw new InvalidOperationException(ExecutionStringManager.CantChangeNameAfterStart);
VerifyInternalState();
_name = value;
}
}
}
///
/// Returns the configuration parameters that can be shared by all services
///
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 TrackingServiceReplacement
{
get
{
return _trackingServiceReplacement;
}
}
/// Adds a service to this container.
/// The service to add
///
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