Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Hosting / WorkflowInstanceExtensionManager.cs / 1305376 / WorkflowInstanceExtensionManager.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.Activities.Hosting
{
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
using System.Activities.Tracking;
// One workflow host should have one manager, and one manager should have one catalog.
// One workflow instance should have one container as the instance itself would be
// added as one extension to the container as well
public class WorkflowInstanceExtensionManager
{
// using an empty list instead of null simplifies our calculations immensely
internal static List> EmptyExtensionProviders = new List>(0);
internal static List EmptySingletonExtensions = new List(0);
bool isReadonly;
List additionalSingletonExtensions;
List allSingletonExtensions;
bool hasSingletonTrackingParticipant;
bool hasSingletonPersistenceModule;
public WorkflowInstanceExtensionManager()
{
}
internal SymbolResolver SymbolResolver
{
get;
private set;
}
internal List SingletonExtensions
{
get;
private set;
}
internal List AdditionalSingletonExtensions
{
get
{
return this.additionalSingletonExtensions;
}
}
internal List> ExtensionProviders
{
get;
private set;
}
internal bool HasSingletonIWorkflowInstanceExtensions
{
get;
private set;
}
internal bool HasSingletonTrackingParticipant
{
get
{
return this.hasSingletonTrackingParticipant;
}
}
internal bool HasSingletonPersistenceModule
{
get
{
return this.hasSingletonPersistenceModule;
}
}
internal bool HasAdditionalSingletonIWorkflowInstanceExtensions
{
get;
private set;
}
// use this method to add the singleton extension
public virtual void Add(object singletonExtension)
{
if (singletonExtension == null)
{
throw FxTrace.Exception.ArgumentNull("singletonExtension");
}
ThrowIfReadOnly();
if (singletonExtension is SymbolResolver)
{
if (this.SymbolResolver != null)
{
throw FxTrace.Exception.Argument("singletonExtension", SR.SymbolResolverAlreadyExists);
}
this.SymbolResolver = (SymbolResolver)singletonExtension;
}
else
{
if (singletonExtension is IWorkflowInstanceExtension)
{
HasSingletonIWorkflowInstanceExtensions = true;
}
if (!this.HasSingletonTrackingParticipant && singletonExtension is TrackingParticipant)
{
this.hasSingletonTrackingParticipant = true;
}
if (!this.HasSingletonPersistenceModule && singletonExtension is IPersistencePipelineModule)
{
this.hasSingletonPersistenceModule = true;
}
}
if (this.SingletonExtensions == null)
{
this.SingletonExtensions = new List();
}
this.SingletonExtensions.Add(singletonExtension);
}
// use this method to add a per-instance extension
public virtual void Add(Func extensionCreationFunction) where T : class
{
if (extensionCreationFunction == null)
{
throw FxTrace.Exception.ArgumentNull("extensionCreationFunction");
}
ThrowIfReadOnly();
if (this.ExtensionProviders == null)
{
this.ExtensionProviders = new List>();
}
this.ExtensionProviders.Add(new KeyValuePair(typeof(T), new WorkflowInstanceExtensionProvider(extensionCreationFunction)));
}
internal List GetAllSingletonExtensions()
{
return this.allSingletonExtensions;
}
internal void AddAllExtensionTypes(HashSet extensionTypes)
{
Fx.Assert(this.isReadonly, "should be read only at this point");
for (int i = 0; i < this.SingletonExtensions.Count; i++)
{
extensionTypes.Add(this.SingletonExtensions[i].GetType());
}
for (int i = 0; i < this.ExtensionProviders.Count; i++)
{
extensionTypes.Add(this.ExtensionProviders[i].Key);
}
}
internal static WorkflowInstanceExtensionCollection CreateInstanceExtensions(Activity workflowDefinition, WorkflowInstanceExtensionManager extensionManager)
{
Fx.Assert(workflowDefinition.IsRuntimeReady, "activity should be ready with extensions after a successful CacheMetadata call");
if (extensionManager != null)
{
extensionManager.MakeReadOnly();
return new WorkflowInstanceExtensionCollection(workflowDefinition, extensionManager);
}
else if ((workflowDefinition.DefaultExtensionsCount > 0) || (workflowDefinition.RequiredExtensionTypesCount > 0))
{
return new WorkflowInstanceExtensionCollection(workflowDefinition, null);
}
else
{
return null;
}
}
internal static void AddExtensionClosure(object newExtension, ref List targetCollection, ref bool addedTrackingParticipant, ref bool addedPersistenceModule)
{
// see if we need to process "additional" extensions
IWorkflowInstanceExtension currentInstanceExtension = newExtension as IWorkflowInstanceExtension;
if (currentInstanceExtension == null)
{
return; // bail early
}
Queue additionalInstanceExtensions = null;
if (targetCollection == null)
{
targetCollection = new List();
}
while (currentInstanceExtension != null)
{
IEnumerable additionalExtensions = currentInstanceExtension.GetAdditionalExtensions();
if (additionalExtensions != null)
{
foreach (object additionalExtension in additionalExtensions)
{
targetCollection.Add(additionalExtension);
if (additionalExtension is IWorkflowInstanceExtension)
{
if (additionalInstanceExtensions == null)
{
additionalInstanceExtensions = new Queue();
}
additionalInstanceExtensions.Enqueue((IWorkflowInstanceExtension)additionalExtension);
}
if (!addedTrackingParticipant && additionalExtension is TrackingParticipant)
{
addedTrackingParticipant = true;
}
if (!addedPersistenceModule && additionalExtension is IPersistencePipelineModule)
{
addedPersistenceModule = true;
}
}
}
if (additionalInstanceExtensions != null && additionalInstanceExtensions.Count > 0)
{
currentInstanceExtension = additionalInstanceExtensions.Dequeue();
}
else
{
currentInstanceExtension = null;
}
}
}
public void MakeReadOnly()
{
// if any singleton extensions have dependents, calculate them now so that we're only
// doing this process once per-host
if (!this.isReadonly)
{
if (this.SingletonExtensions != null)
{
if (HasSingletonIWorkflowInstanceExtensions)
{
foreach (IWorkflowInstanceExtension additionalExtensionProvider in this.SingletonExtensions.OfType())
{
AddExtensionClosure(additionalExtensionProvider, ref this.additionalSingletonExtensions, ref this.hasSingletonTrackingParticipant, ref this.hasSingletonPersistenceModule);
}
if (this.AdditionalSingletonExtensions != null)
{
for (int i = 0; i < this.AdditionalSingletonExtensions.Count; i++)
{
object extension = this.AdditionalSingletonExtensions[i];
if (extension is IWorkflowInstanceExtension)
{
HasAdditionalSingletonIWorkflowInstanceExtensions = true;
break;
}
}
}
}
this.allSingletonExtensions = this.SingletonExtensions;
if (this.AdditionalSingletonExtensions != null && this.AdditionalSingletonExtensions.Count > 0)
{
this.allSingletonExtensions = new List(this.SingletonExtensions);
this.allSingletonExtensions.AddRange(this.AdditionalSingletonExtensions);
}
}
else
{
this.SingletonExtensions = EmptySingletonExtensions;
this.allSingletonExtensions = EmptySingletonExtensions;
}
if (this.ExtensionProviders == null)
{
this.ExtensionProviders = EmptyExtensionProviders;
}
this.isReadonly = true;
}
}
void ThrowIfReadOnly()
{
if (this.isReadonly)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ExtensionsCannotBeModified));
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.