You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,83 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime;
|
||||
|
||||
[DataContract]
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public sealed class BookmarkInfo
|
||||
{
|
||||
string bookmarkName;
|
||||
BookmarkScopeInfo scopeInfo;
|
||||
string ownerDisplayName;
|
||||
|
||||
internal BookmarkInfo(string bookmarkName, string ownerDisplayName, BookmarkScopeInfo scopeInfo)
|
||||
{
|
||||
this.BookmarkName = bookmarkName;
|
||||
this.OwnerDisplayName = ownerDisplayName;
|
||||
this.ScopeInfo = scopeInfo;
|
||||
}
|
||||
|
||||
public string BookmarkName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.bookmarkName;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.bookmarkName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string OwnerDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ownerDisplayName;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.ownerDisplayName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BookmarkScopeInfo ScopeInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.scopeInfo;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.scopeInfo = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "BookmarkName")]
|
||||
internal string SerializedBookmarkName
|
||||
{
|
||||
get { return this.BookmarkName; }
|
||||
set { this.BookmarkName = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "OwnerDisplayName")]
|
||||
internal string SerializedOwnerDisplayName
|
||||
{
|
||||
get { return this.OwnerDisplayName; }
|
||||
set { this.OwnerDisplayName = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "ScopeInfo")]
|
||||
internal BookmarkScopeInfo SerializedScopeInfo
|
||||
{
|
||||
get { return this.ScopeInfo; }
|
||||
set { this.ScopeInfo = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime;
|
||||
|
||||
[DataContract]
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public sealed class BookmarkScopeInfo
|
||||
{
|
||||
Guid id;
|
||||
string temporaryId;
|
||||
|
||||
internal BookmarkScopeInfo(Guid id)
|
||||
{
|
||||
this.Id = id;
|
||||
}
|
||||
|
||||
internal BookmarkScopeInfo(string temporaryId)
|
||||
{
|
||||
this.TemporaryId = temporaryId;
|
||||
}
|
||||
|
||||
public bool IsInitialized
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.TemporaryId == null;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.id = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string TemporaryId
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.temporaryId;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.temporaryId = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "Id")]
|
||||
internal Guid SerializedId
|
||||
{
|
||||
get { return this.Id; }
|
||||
set { this.Id = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "TemporaryId")]
|
||||
internal string SerializedTemporaryId
|
||||
{
|
||||
get { return this.TemporaryId; }
|
||||
set { this.TemporaryId = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
// overriden by extensions that want to contribute additional
|
||||
// extensions and/or get notified when they are being used with a WorkflowInstance
|
||||
public interface IWorkflowInstanceExtension
|
||||
{
|
||||
IEnumerable<object> GetAdditionalExtensions();
|
||||
|
||||
// called with the targe instance under WorkflowInstance.Initialize
|
||||
void SetInstance(WorkflowInstanceProxy instance);
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
[DataContract]
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public sealed class LocationInfo
|
||||
{
|
||||
string name;
|
||||
string ownerDisplayName;
|
||||
object value;
|
||||
|
||||
internal LocationInfo(string name, string ownerDisplayName, object value)
|
||||
{
|
||||
this.Name = name;
|
||||
this.OwnerDisplayName = ownerDisplayName;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.name = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string OwnerDisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ownerDisplayName;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.ownerDisplayName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "Name")]
|
||||
internal string SerializedName
|
||||
{
|
||||
get { return this.Name; }
|
||||
set { this.Name = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "OwnerDisplayName")]
|
||||
internal string SerializedOwnerDisplayName
|
||||
{
|
||||
get { return this.OwnerDisplayName; }
|
||||
set { this.OwnerDisplayName = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "Value")]
|
||||
internal object SerializedValue
|
||||
{
|
||||
get { return this.Value; }
|
||||
set { this.Value = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,424 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime;
|
||||
|
||||
[SuppressMessage(FxCop.Category.Naming, FxCop.Rule.IdentifiersShouldHaveCorrectSuffix,
|
||||
Justification = "Approved name")]
|
||||
public sealed class SymbolResolver : IDictionary<string, object>
|
||||
{
|
||||
Dictionary<string, ExternalLocationReference> symbols;
|
||||
|
||||
public SymbolResolver()
|
||||
{
|
||||
this.symbols = new Dictionary<string, ExternalLocationReference>();
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return this.symbols.Count; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get { return this.symbols.Keys; }
|
||||
}
|
||||
|
||||
public ICollection<object> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
List<object> values = new List<object>(this.symbols.Count);
|
||||
|
||||
foreach (ExternalLocationReference reference in this.symbols.Values)
|
||||
{
|
||||
values.Add(reference.Value);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
public object this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
// We don't need to do any existence checks since we want the dictionary exception to bubble up
|
||||
return this.symbols[key].Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
this.symbols[key] = CreateReference(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string key, object value)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
this.symbols.Add(key, CreateReference(key, value));
|
||||
}
|
||||
|
||||
public void Add(string key, Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("type");
|
||||
}
|
||||
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
this.symbols.Add(key, new ExternalLocationReference(key, type, TypeHelper.GetDefaultValueForType(type)));
|
||||
}
|
||||
|
||||
public void Add(string key, object value, Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("type");
|
||||
}
|
||||
|
||||
if (!TypeHelper.AreTypesCompatible(value, type))
|
||||
{
|
||||
throw FxTrace.Exception.Argument("value", SR.ValueMustBeAssignableToType);
|
||||
}
|
||||
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
this.symbols.Add(key, new ExternalLocationReference(key, type, value));
|
||||
}
|
||||
|
||||
ExternalLocationReference CreateReference(string name, object value)
|
||||
{
|
||||
Type valueType = TypeHelper.ObjectType;
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
valueType = value.GetType();
|
||||
}
|
||||
|
||||
return new ExternalLocationReference(name, valueType, value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, object> item)
|
||||
{
|
||||
Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
this.symbols.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, object> item)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
ExternalLocationReference reference;
|
||||
if (this.symbols.TryGetValue(item.Key, out reference))
|
||||
{
|
||||
return item.Value == reference.Value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
return this.symbols.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("array");
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentOutOfRange("arrayIndex", arrayIndex, SR.CopyToIndexOutOfRange);
|
||||
}
|
||||
|
||||
if (array.Rank > 1)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("array", SR.CopyToRankMustBeOne);
|
||||
}
|
||||
|
||||
if (this.symbols.Count > array.Length - arrayIndex)
|
||||
{
|
||||
throw FxTrace.Exception.Argument("array", SR.CopyToNotEnoughSpaceInArray);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, ExternalLocationReference> pair in this.symbols)
|
||||
{
|
||||
Fx.Assert(arrayIndex < array.Length, "We must have room since we validated it.");
|
||||
|
||||
array[arrayIndex] = new KeyValuePair<string, object>(pair.Key, pair.Value.Value);
|
||||
arrayIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<string, ExternalLocationReference> pair in this.symbols)
|
||||
{
|
||||
yield return new KeyValuePair<string, object>(pair.Key, pair.Value.Value);
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<KeyValuePair<string, LocationReference>> GetLocationReferenceEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<string, ExternalLocationReference> pair in this.symbols)
|
||||
{
|
||||
yield return new KeyValuePair<string, LocationReference>(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
return this.symbols.Remove(key);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, object> item)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
ExternalLocationReference reference;
|
||||
if (this.symbols.TryGetValue(item.Key, out reference))
|
||||
{
|
||||
if (reference.Value == item.Value)
|
||||
{
|
||||
this.symbols.Remove(item.Key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out object value)
|
||||
{
|
||||
// We don't need to check key for null since we want the exception to bubble up from the inner dictionary
|
||||
|
||||
ExternalLocationReference reference;
|
||||
if (this.symbols.TryGetValue(key, out reference))
|
||||
{
|
||||
value = reference.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool TryGetLocationReference(string name, out LocationReference result)
|
||||
{
|
||||
ExternalLocationReference reference;
|
||||
if (this.symbols.TryGetValue(name, out reference))
|
||||
{
|
||||
result = reference;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool IsVisible(LocationReference locationReference)
|
||||
{
|
||||
// We only check for null since string.Empty is
|
||||
// actually allowed.
|
||||
if (locationReference.Name == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExternalLocationReference externalLocationReference;
|
||||
if (this.symbols.TryGetValue(locationReference.Name, out externalLocationReference))
|
||||
{
|
||||
if (externalLocationReference.Type == locationReference.Type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Location GetLocation(string name, Type type)
|
||||
{
|
||||
ExternalLocationReference reference;
|
||||
if (this.symbols.TryGetValue(name, out reference))
|
||||
{
|
||||
if (reference.Type == type)
|
||||
{
|
||||
// We're the same reference
|
||||
return reference.Location;
|
||||
}
|
||||
}
|
||||
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.SymbolResolverDoesNotHaveSymbol(name, type)));
|
||||
}
|
||||
|
||||
public LocationReferenceEnvironment AsLocationReferenceEnvironment()
|
||||
{
|
||||
return new SymbolResolverLocationReferenceEnvironment(this);
|
||||
}
|
||||
|
||||
class SymbolResolverLocationReferenceEnvironment : LocationReferenceEnvironment
|
||||
{
|
||||
SymbolResolver symbolResolver;
|
||||
|
||||
public SymbolResolverLocationReferenceEnvironment(SymbolResolver symbolResolver)
|
||||
{
|
||||
this.symbolResolver = symbolResolver;
|
||||
}
|
||||
|
||||
public override Activity Root
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsVisible(LocationReference locationReference)
|
||||
{
|
||||
if (locationReference == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("locationReference");
|
||||
}
|
||||
|
||||
return this.symbolResolver.IsVisible(locationReference);
|
||||
}
|
||||
|
||||
public override bool TryGetLocationReference(string name, out LocationReference result)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNullOrEmpty("name");
|
||||
}
|
||||
|
||||
return this.symbolResolver.TryGetLocationReference(name, out result);
|
||||
}
|
||||
|
||||
public override IEnumerable<LocationReference> GetLocationReferences()
|
||||
{
|
||||
List<LocationReference> list = new List<LocationReference>();
|
||||
foreach (ExternalLocationReference item in this.symbolResolver.symbols.Values)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
class ExternalLocationReference : LocationReference
|
||||
{
|
||||
ExternalLocation location;
|
||||
string name;
|
||||
Type type;
|
||||
|
||||
public ExternalLocationReference(string name, Type type, object value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.location = new ExternalLocation(this.type, value);
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.location.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.location;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string NameCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Type TypeCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
|
||||
public override Location GetLocation(ActivityContext context)
|
||||
{
|
||||
SymbolResolver resolver = context.GetExtension<SymbolResolver>();
|
||||
|
||||
if (resolver == null)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CanNotFindSymbolResolverInWorkflowInstanceExtensions));
|
||||
}
|
||||
|
||||
return resolver.GetLocation(this.Name, this.Type);
|
||||
}
|
||||
|
||||
class ExternalLocation : Location
|
||||
{
|
||||
Type type;
|
||||
object value;
|
||||
|
||||
public ExternalLocation(Type type, object value)
|
||||
{
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public override Type LocationType
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
|
||||
protected override object ValueCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ExternalLocationsGetOnly));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,476 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System.Activities.Tracking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime;
|
||||
|
||||
class WorkflowInstanceExtensionCollection
|
||||
{
|
||||
List<KeyValuePair<WorkflowInstanceExtensionProvider, object>> instanceExtensions;
|
||||
List<object> additionalInstanceExtensions;
|
||||
List<object> allSingletonExtensions;
|
||||
bool hasTrackingParticipant;
|
||||
bool hasPersistenceModule;
|
||||
bool shouldSetInstanceForInstanceExtensions;
|
||||
|
||||
// cache for cases where we have a single match
|
||||
Dictionary<Type, object> singleTypeCache;
|
||||
|
||||
List<IWorkflowInstanceExtension> workflowInstanceExtensions;
|
||||
|
||||
// optimization for common extension in a loop/parallel (like Compensation or Send)
|
||||
Type lastTypeCached;
|
||||
object lastObjectCached;
|
||||
|
||||
// temporary pointer to our parent manager between ctor and Initialize
|
||||
WorkflowInstanceExtensionManager extensionManager;
|
||||
|
||||
internal WorkflowInstanceExtensionCollection(Activity workflowDefinition, WorkflowInstanceExtensionManager extensionManager)
|
||||
{
|
||||
this.extensionManager = extensionManager;
|
||||
|
||||
int extensionProviderCount = 0;
|
||||
if (extensionManager != null)
|
||||
{
|
||||
extensionProviderCount = extensionManager.ExtensionProviders.Count;
|
||||
this.hasTrackingParticipant = extensionManager.HasSingletonTrackingParticipant;
|
||||
this.hasPersistenceModule = extensionManager.HasSingletonPersistenceModule;
|
||||
|
||||
// create an uber-IEnumerable to simplify our iteration code
|
||||
this.allSingletonExtensions = this.extensionManager.GetAllSingletonExtensions();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.allSingletonExtensions = WorkflowInstanceExtensionManager.EmptySingletonExtensions;
|
||||
}
|
||||
|
||||
// Resolve activity extensions
|
||||
Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders;
|
||||
Dictionary<Type, WorkflowInstanceExtensionProvider> filteredActivityExtensionProviders = null;
|
||||
HashSet<Type> requiredActivityExtensionTypes;
|
||||
if (workflowDefinition.GetActivityExtensionInformation(out activityExtensionProviders, out requiredActivityExtensionTypes))
|
||||
{
|
||||
// a) filter out the extension Types that were already configured by the host. Note that only "primary" extensions are in play here, not
|
||||
// "additional" extensions
|
||||
HashSet<Type> allExtensionTypes = new HashSet<Type>();
|
||||
if (extensionManager != null)
|
||||
{
|
||||
extensionManager.AddAllExtensionTypes(allExtensionTypes);
|
||||
}
|
||||
|
||||
if (activityExtensionProviders != null)
|
||||
{
|
||||
filteredActivityExtensionProviders = new Dictionary<Type, WorkflowInstanceExtensionProvider>(activityExtensionProviders.Count);
|
||||
foreach (KeyValuePair<Type, WorkflowInstanceExtensionProvider> keyedActivityExtensionProvider in activityExtensionProviders)
|
||||
{
|
||||
Type newExtensionProviderType = keyedActivityExtensionProvider.Key;
|
||||
if (!TypeHelper.ContainsCompatibleType(allExtensionTypes, newExtensionProviderType))
|
||||
{
|
||||
// first see if the new provider supersedes any existing ones
|
||||
List<Type> typesToRemove = null;
|
||||
bool skipNewExtensionProvider = false;
|
||||
foreach (Type existingExtensionProviderType in filteredActivityExtensionProviders.Keys)
|
||||
{
|
||||
// Use AreReferenceTypesCompatible for performance since we know that all of these must be reference types
|
||||
if (TypeHelper.AreReferenceTypesCompatible(existingExtensionProviderType, newExtensionProviderType))
|
||||
{
|
||||
skipNewExtensionProvider = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TypeHelper.AreReferenceTypesCompatible(newExtensionProviderType, existingExtensionProviderType))
|
||||
{
|
||||
if (typesToRemove == null)
|
||||
{
|
||||
typesToRemove = new List<Type>();
|
||||
}
|
||||
typesToRemove.Add(existingExtensionProviderType);
|
||||
}
|
||||
}
|
||||
|
||||
// prune unnecessary extension providers (either superseded by the new extension or by an existing extension that supersedes them both)
|
||||
if (typesToRemove != null)
|
||||
{
|
||||
for (int i = 0; i < typesToRemove.Count; i++)
|
||||
{
|
||||
filteredActivityExtensionProviders.Remove(typesToRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// and add a new extension if necessary
|
||||
if (!skipNewExtensionProvider)
|
||||
{
|
||||
filteredActivityExtensionProviders.Add(newExtensionProviderType, keyedActivityExtensionProvider.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filteredActivityExtensionProviders.Count > 0)
|
||||
{
|
||||
allExtensionTypes.UnionWith(filteredActivityExtensionProviders.Keys);
|
||||
extensionProviderCount += filteredActivityExtensionProviders.Count;
|
||||
}
|
||||
}
|
||||
|
||||
// b) Validate that all required extensions will be provided
|
||||
if (requiredActivityExtensionTypes != null && requiredActivityExtensionTypes.Count > 0)
|
||||
{
|
||||
foreach (Type requiredType in requiredActivityExtensionTypes)
|
||||
{
|
||||
if (!TypeHelper.ContainsCompatibleType(allExtensionTypes, requiredType))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new ValidationException(SR.RequiredExtensionTypeNotFound(requiredType.ToString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, if our checks of passed, resolve our delegates
|
||||
if (extensionProviderCount > 0)
|
||||
{
|
||||
this.instanceExtensions = new List<KeyValuePair<WorkflowInstanceExtensionProvider, object>>(extensionProviderCount);
|
||||
|
||||
if (extensionManager != null)
|
||||
{
|
||||
List<KeyValuePair<Type, WorkflowInstanceExtensionProvider>> extensionProviders = extensionManager.ExtensionProviders;
|
||||
for (int i = 0; i < extensionProviders.Count; i++)
|
||||
{
|
||||
KeyValuePair<Type, WorkflowInstanceExtensionProvider> extensionProvider = extensionProviders[i];
|
||||
AddInstanceExtension(extensionProvider.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredActivityExtensionProviders != null)
|
||||
{
|
||||
foreach (WorkflowInstanceExtensionProvider extensionProvider in filteredActivityExtensionProviders.Values)
|
||||
{
|
||||
AddInstanceExtension(extensionProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddInstanceExtension(WorkflowInstanceExtensionProvider extensionProvider)
|
||||
{
|
||||
Fx.Assert(this.instanceExtensions != null, "instanceExtensions should be setup by now");
|
||||
object newExtension = extensionProvider.ProvideValue();
|
||||
if (newExtension is SymbolResolver)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.SymbolResolverMustBeSingleton));
|
||||
}
|
||||
|
||||
// for IWorkflowInstance we key off the type of the value, not the declared type
|
||||
if (!this.shouldSetInstanceForInstanceExtensions && newExtension is IWorkflowInstanceExtension)
|
||||
{
|
||||
this.shouldSetInstanceForInstanceExtensions = true;
|
||||
}
|
||||
if (!this.hasTrackingParticipant && extensionProvider.IsMatch<TrackingParticipant>(newExtension))
|
||||
{
|
||||
this.hasTrackingParticipant = true;
|
||||
}
|
||||
if (!this.hasPersistenceModule && extensionProvider.IsMatch<IPersistencePipelineModule>(newExtension))
|
||||
{
|
||||
this.hasPersistenceModule = true;
|
||||
}
|
||||
|
||||
this.instanceExtensions.Add(new KeyValuePair<WorkflowInstanceExtensionProvider, object>(extensionProvider, newExtension));
|
||||
|
||||
WorkflowInstanceExtensionManager.AddExtensionClosure(newExtension, ref this.additionalInstanceExtensions, ref this.hasTrackingParticipant, ref this.hasPersistenceModule);
|
||||
}
|
||||
|
||||
internal bool HasPersistenceModule
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.hasPersistenceModule;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool HasTrackingParticipant
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.hasTrackingParticipant;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasWorkflowInstanceExtensions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.workflowInstanceExtensions != null && this.workflowInstanceExtensions.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public List<IWorkflowInstanceExtension> WorkflowInstanceExtensions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.workflowInstanceExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
if (this.extensionManager != null)
|
||||
{
|
||||
// if we have any singleton IWorkflowInstanceExtensions, initialize them first
|
||||
// All validation logic for singletons is done through WorkflowInstanceExtensionManager
|
||||
if (this.extensionManager.HasSingletonIWorkflowInstanceExtensions)
|
||||
{
|
||||
SetInstance(this.extensionManager.SingletonExtensions);
|
||||
|
||||
if (this.extensionManager.HasAdditionalSingletonIWorkflowInstanceExtensions)
|
||||
{
|
||||
SetInstance(this.extensionManager.AdditionalSingletonExtensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldSetInstanceForInstanceExtensions)
|
||||
{
|
||||
for (int i = 0; i < this.instanceExtensions.Count; i++)
|
||||
{
|
||||
KeyValuePair<WorkflowInstanceExtensionProvider, object> keyedExtension = this.instanceExtensions[i];
|
||||
// for IWorkflowInstance we key off the type of the value, not the declared type
|
||||
IWorkflowInstanceExtension workflowInstanceExtension = keyedExtension.Value as IWorkflowInstanceExtension;
|
||||
|
||||
if (workflowInstanceExtension != null)
|
||||
{
|
||||
if (this.workflowInstanceExtensions == null)
|
||||
{
|
||||
this.workflowInstanceExtensions = new List<IWorkflowInstanceExtension>();
|
||||
}
|
||||
|
||||
this.workflowInstanceExtensions.Add(workflowInstanceExtension);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.additionalInstanceExtensions != null)
|
||||
{
|
||||
SetInstance(this.additionalInstanceExtensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetInstance(List<object> extensionsList)
|
||||
{
|
||||
for (int i = 0; i < extensionsList.Count; i++)
|
||||
{
|
||||
object extension = extensionsList[i];
|
||||
if (extension is IWorkflowInstanceExtension)
|
||||
{
|
||||
if (this.workflowInstanceExtensions == null)
|
||||
{
|
||||
this.workflowInstanceExtensions = new List<IWorkflowInstanceExtension>();
|
||||
}
|
||||
|
||||
this.workflowInstanceExtensions.Add((IWorkflowInstanceExtension)extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T Find<T>()
|
||||
where T : class
|
||||
{
|
||||
T result = null;
|
||||
|
||||
object cachedExtension;
|
||||
if (TryGetCachedExtension(typeof(T), out cachedExtension))
|
||||
{
|
||||
return (T)cachedExtension;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// when we have support for context.GetExtensions<T>(), then change from early break to ThrowOnMultipleMatches ("There are more than one matched extensions found which is not allowed with GetExtension method call. Please use GetExtensions method instead.")
|
||||
for (int i = 0; i < this.allSingletonExtensions.Count; i++)
|
||||
{
|
||||
object extension = this.allSingletonExtensions[i];
|
||||
result = extension as T;
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.instanceExtensions != null)
|
||||
{
|
||||
for (int i = 0; i < this.instanceExtensions.Count; i++)
|
||||
{
|
||||
KeyValuePair<WorkflowInstanceExtensionProvider, object> keyedExtension = this.instanceExtensions[i];
|
||||
if (keyedExtension.Key.IsMatch<T>(keyedExtension.Value))
|
||||
{
|
||||
result = (T)keyedExtension.Value;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.additionalInstanceExtensions != null)
|
||||
{
|
||||
for (int i = 0; i < this.additionalInstanceExtensions.Count; i++)
|
||||
{
|
||||
object additionalExtension = this.additionalInstanceExtensions[i];
|
||||
result = additionalExtension as T;
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
CacheExtension(result);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> FindAll<T>()
|
||||
where T : class
|
||||
{
|
||||
return FindAll<T>(false);
|
||||
}
|
||||
|
||||
IEnumerable<T> FindAll<T>(bool useObjectTypeForComparison)
|
||||
where T : class
|
||||
{
|
||||
// sometimes we match the single case even when you ask for multiple
|
||||
object cachedExtension;
|
||||
if (TryGetCachedExtension(typeof(T), out cachedExtension))
|
||||
{
|
||||
yield return (T)cachedExtension;
|
||||
}
|
||||
else
|
||||
{
|
||||
T lastExtension = null;
|
||||
bool hasMultiple = false;
|
||||
|
||||
foreach (T extension in this.allSingletonExtensions.OfType<T>())
|
||||
{
|
||||
if (lastExtension == null)
|
||||
{
|
||||
lastExtension = extension;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasMultiple = true;
|
||||
}
|
||||
|
||||
yield return extension;
|
||||
}
|
||||
|
||||
foreach (T extension in GetInstanceExtensions<T>(useObjectTypeForComparison))
|
||||
{
|
||||
if (lastExtension == null)
|
||||
{
|
||||
lastExtension = extension;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasMultiple = true;
|
||||
}
|
||||
|
||||
yield return extension;
|
||||
}
|
||||
|
||||
if (!hasMultiple)
|
||||
{
|
||||
CacheExtension(lastExtension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<T> GetInstanceExtensions<T>(bool useObjectTypeForComparison) where T : class
|
||||
{
|
||||
if (this.instanceExtensions != null)
|
||||
{
|
||||
for (int i = 0; i < this.instanceExtensions.Count; i++)
|
||||
{
|
||||
KeyValuePair<WorkflowInstanceExtensionProvider, object> keyedExtension = this.instanceExtensions[i];
|
||||
if ((useObjectTypeForComparison && keyedExtension.Value is T)
|
||||
|| keyedExtension.Key.IsMatch<T>(keyedExtension.Value))
|
||||
{
|
||||
yield return (T)keyedExtension.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.additionalInstanceExtensions != null)
|
||||
{
|
||||
foreach (object additionalExtension in this.additionalInstanceExtensions)
|
||||
{
|
||||
if (additionalExtension is T)
|
||||
{
|
||||
yield return (T)additionalExtension;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// we should only call dispose on instance extensions, since those are
|
||||
// the only ones we created
|
||||
foreach (IDisposable disposableExtension in GetInstanceExtensions<IDisposable>(true))
|
||||
{
|
||||
disposableExtension.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
foreach (ICancelable cancelableExtension in GetInstanceExtensions<ICancelable>(true))
|
||||
{
|
||||
cancelableExtension.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void CacheExtension<T>(T extension)
|
||||
where T : class
|
||||
{
|
||||
if (extension != null)
|
||||
{
|
||||
CacheExtension(typeof(T), extension);
|
||||
}
|
||||
}
|
||||
|
||||
void CacheExtension(Type extensionType, object extension)
|
||||
{
|
||||
if (extension != null)
|
||||
{
|
||||
if (this.singleTypeCache == null)
|
||||
{
|
||||
this.singleTypeCache = new Dictionary<Type, object>();
|
||||
}
|
||||
|
||||
this.lastTypeCached = extensionType;
|
||||
this.lastObjectCached = extension;
|
||||
this.singleTypeCache[extensionType] = extension;
|
||||
}
|
||||
}
|
||||
|
||||
bool TryGetCachedExtension(Type type, out object extension)
|
||||
{
|
||||
if (this.singleTypeCache == null)
|
||||
{
|
||||
extension = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (object.ReferenceEquals(type, this.lastTypeCached))
|
||||
{
|
||||
extension = this.lastObjectCached;
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.singleTypeCache.TryGetValue(type, out extension);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,293 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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<KeyValuePair<Type, WorkflowInstanceExtensionProvider>> EmptyExtensionProviders = new List<KeyValuePair<Type, WorkflowInstanceExtensionProvider>>(0);
|
||||
internal static List<object> EmptySingletonExtensions = new List<object>(0);
|
||||
|
||||
bool isReadonly;
|
||||
List<object> additionalSingletonExtensions;
|
||||
List<object> allSingletonExtensions;
|
||||
|
||||
bool hasSingletonTrackingParticipant;
|
||||
bool hasSingletonPersistenceModule;
|
||||
|
||||
public WorkflowInstanceExtensionManager()
|
||||
{
|
||||
}
|
||||
|
||||
internal SymbolResolver SymbolResolver
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
internal List<object> SingletonExtensions
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
internal List<object> AdditionalSingletonExtensions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.additionalSingletonExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
internal List<KeyValuePair<Type, WorkflowInstanceExtensionProvider>> 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<object>();
|
||||
}
|
||||
|
||||
this.SingletonExtensions.Add(singletonExtension);
|
||||
}
|
||||
|
||||
// use this method to add a per-instance extension
|
||||
public virtual void Add<T>(Func<T> extensionCreationFunction) where T : class
|
||||
{
|
||||
if (extensionCreationFunction == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("extensionCreationFunction");
|
||||
}
|
||||
ThrowIfReadOnly();
|
||||
|
||||
if (this.ExtensionProviders == null)
|
||||
{
|
||||
this.ExtensionProviders = new List<KeyValuePair<Type, WorkflowInstanceExtensionProvider>>();
|
||||
}
|
||||
|
||||
this.ExtensionProviders.Add(new KeyValuePair<Type, WorkflowInstanceExtensionProvider>(typeof(T), new WorkflowInstanceExtensionProvider<T>(extensionCreationFunction)));
|
||||
}
|
||||
|
||||
internal List<object> GetAllSingletonExtensions()
|
||||
{
|
||||
return this.allSingletonExtensions;
|
||||
}
|
||||
|
||||
internal void AddAllExtensionTypes(HashSet<Type> 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<object> 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<IWorkflowInstanceExtension> additionalInstanceExtensions = null;
|
||||
if (targetCollection == null)
|
||||
{
|
||||
targetCollection = new List<object>();
|
||||
}
|
||||
|
||||
while (currentInstanceExtension != null)
|
||||
{
|
||||
IEnumerable<object> additionalExtensions = currentInstanceExtension.GetAdditionalExtensions();
|
||||
if (additionalExtensions != null)
|
||||
{
|
||||
foreach (object additionalExtension in additionalExtensions)
|
||||
{
|
||||
targetCollection.Add(additionalExtension);
|
||||
if (additionalExtension is IWorkflowInstanceExtension)
|
||||
{
|
||||
if (additionalInstanceExtensions == null)
|
||||
{
|
||||
additionalInstanceExtensions = new Queue<IWorkflowInstanceExtension>();
|
||||
}
|
||||
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<IWorkflowInstanceExtension>())
|
||||
{
|
||||
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<object>(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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System.Runtime;
|
||||
|
||||
abstract class WorkflowInstanceExtensionProvider
|
||||
{
|
||||
protected WorkflowInstanceExtensionProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
protected bool GeneratedTypeMatchesDeclaredType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public abstract object ProvideValue();
|
||||
|
||||
public bool IsMatch<TTarget>(object value)
|
||||
where TTarget : class
|
||||
{
|
||||
Fx.Assert(value != null, "extension providers never return a null extension");
|
||||
if (value is TTarget)
|
||||
{
|
||||
if (this.GeneratedTypeMatchesDeclaredType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TypeHelper.AreReferenceTypesCompatible(this.Type, typeof(TTarget));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WorkflowInstanceExtensionProvider<T> : WorkflowInstanceExtensionProvider
|
||||
where T : class
|
||||
{
|
||||
Func<T> providerFunction;
|
||||
bool hasGeneratedValue;
|
||||
|
||||
public WorkflowInstanceExtensionProvider(Func<T> providerFunction)
|
||||
: base()
|
||||
{
|
||||
this.providerFunction = providerFunction;
|
||||
base.Type = typeof(T);
|
||||
}
|
||||
|
||||
public override object ProvideValue()
|
||||
{
|
||||
T value = this.providerFunction();
|
||||
if (!this.hasGeneratedValue)
|
||||
{
|
||||
base.GeneratedTypeMatchesDeclaredType = object.ReferenceEquals(value.GetType(), this.Type);
|
||||
this.hasGeneratedValue = true;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
|
||||
public sealed class WorkflowInstanceProxy
|
||||
{
|
||||
WorkflowInstance instance;
|
||||
|
||||
internal WorkflowInstanceProxy(WorkflowInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public Guid Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.instance.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public Activity WorkflowDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.instance.WorkflowDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
public IAsyncResult BeginResumeBookmark(Bookmark bookmark, object value, AsyncCallback callback, object state)
|
||||
{
|
||||
return BeginResumeBookmark(bookmark, value, TimeSpan.MaxValue, callback, state);
|
||||
}
|
||||
|
||||
public IAsyncResult BeginResumeBookmark(Bookmark bookmark, object value, TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
TimeoutHelper.ThrowIfNegativeArgument(timeout);
|
||||
|
||||
return this.instance.OnBeginResumeBookmark(bookmark, value, timeout, callback, state);
|
||||
}
|
||||
|
||||
public BookmarkResumptionResult EndResumeBookmark(IAsyncResult result)
|
||||
{
|
||||
return this.instance.OnEndResumeBookmark(result);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Hosting
|
||||
{
|
||||
using System;
|
||||
|
||||
public enum WorkflowInstanceState
|
||||
{
|
||||
Idle,
|
||||
Runnable,
|
||||
Complete,
|
||||
Aborted // only Abort is valid
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user