Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -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; }
}
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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);
}
}

View File

@@ -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; }
}
}
}

View File

@@ -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));
}
}
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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));
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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
}
}