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,33 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security;
|
||||
|
||||
[DataContract]
|
||||
class ActivityCompletionCallbackWrapper : CompletionCallbackWrapper
|
||||
{
|
||||
static readonly Type completionCallbackType = typeof(CompletionCallback);
|
||||
static readonly Type[] completionCallbackParameters = new Type[] { typeof(NativeActivityContext), typeof(ActivityInstance) };
|
||||
|
||||
public ActivityCompletionCallbackWrapper(CompletionCallback callback, ActivityInstance owningInstance)
|
||||
: base(callback, owningInstance)
|
||||
{
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback",
|
||||
Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
|
||||
[SecuritySafeCritical]
|
||||
protected internal override void Invoke(NativeActivityContext context, ActivityInstance completedInstance)
|
||||
{
|
||||
EnsureCallback(completionCallbackType, completionCallbackParameters);
|
||||
CompletionCallback completionCallback = (CompletionCallback)this.Callback;
|
||||
completionCallback(context, completedInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[DataContract]
|
||||
abstract class ActivityExecutionWorkItem : WorkItem
|
||||
{
|
||||
bool skipActivityInstanceAbort;
|
||||
|
||||
// Used by subclasses in the pooled case
|
||||
protected ActivityExecutionWorkItem()
|
||||
{
|
||||
}
|
||||
|
||||
public ActivityExecutionWorkItem(ActivityInstance activityInstance)
|
||||
: base(activityInstance)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ActivityInstance.State == ActivityInstanceState.Executing;
|
||||
}
|
||||
}
|
||||
|
||||
public override ActivityInstance PropertyManagerOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ActivityInstance;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ClearForReuse()
|
||||
{
|
||||
base.ClearForReuse();
|
||||
this.skipActivityInstanceAbort = false;
|
||||
}
|
||||
|
||||
protected void SetExceptionToPropagateWithoutAbort(Exception exception)
|
||||
{
|
||||
this.ExceptionToPropagate = exception;
|
||||
this.skipActivityInstanceAbort = true;
|
||||
}
|
||||
|
||||
public override void PostProcess(ActivityExecutor executor)
|
||||
{
|
||||
if (this.ExceptionToPropagate != null && !skipActivityInstanceAbort)
|
||||
{
|
||||
executor.AbortActivityInstance(this.ActivityInstance, this.ExceptionToPropagate);
|
||||
}
|
||||
else if (this.ActivityInstance.UpdateState(executor))
|
||||
{
|
||||
// NOTE: exceptionToPropagate could be non-null here if this is a Fault work item.
|
||||
// That means that the next line could potentially overwrite the exception with a
|
||||
// new exception.
|
||||
Exception newException = executor.CompleteActivityInstance(this.ActivityInstance);
|
||||
|
||||
if (newException != null)
|
||||
{
|
||||
this.ExceptionToPropagate = newException;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
b9cf8fe7e52450ceff6d1c34154cba802c4c505e
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Activities.DynamicUpdate;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
[DataContract]
|
||||
class ActivityInstanceReference : ActivityInstanceMap.IActivityReference
|
||||
{
|
||||
ActivityInstance activityInstance;
|
||||
|
||||
internal ActivityInstanceReference(ActivityInstance activity)
|
||||
{
|
||||
this.activityInstance = activity;
|
||||
}
|
||||
|
||||
[DataMember(Name = "activityInstance")]
|
||||
internal ActivityInstance SerializedActivityInstance
|
||||
{
|
||||
get { return this.activityInstance; }
|
||||
set { this.activityInstance = value; }
|
||||
}
|
||||
|
||||
Activity ActivityInstanceMap.IActivityReference.Activity
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityInstance.Activity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ActivityInstance ActivityInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityInstance;
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityInstanceMap.IActivityReference.Load(Activity activity, ActivityInstanceMap instanceMap)
|
||||
{
|
||||
// The conditional calling of ActivityInstance.Load is the value
|
||||
// added by this wrapper class. This is because we can't guarantee
|
||||
// that multiple activities won't have a reference to the same
|
||||
// ActivityInstance.
|
||||
if (this.activityInstance.Activity == null)
|
||||
{
|
||||
((ActivityInstanceMap.IActivityReference)this.activityInstance).Load(activity, instanceMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security;
|
||||
|
||||
[DataContract]
|
||||
class BookmarkCallbackWrapper : CallbackWrapper
|
||||
{
|
||||
static readonly Type bookmarkCallbackType = typeof(BookmarkCallback);
|
||||
static readonly Type[] bookmarkCallbackParameters = new Type[] { typeof(NativeActivityContext), typeof(Bookmark), typeof(object) };
|
||||
|
||||
public BookmarkCallbackWrapper(BookmarkCallback callback, ActivityInstance owningInstance)
|
||||
: this(callback, owningInstance, BookmarkOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public BookmarkCallbackWrapper(BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions bookmarkOptions)
|
||||
: base(callback, owningInstance)
|
||||
{
|
||||
Fx.Assert(callback != null || bookmarkOptions == BookmarkOptions.None, "Either we have a callback or we only allow SingleFire, Blocking bookmarks.");
|
||||
|
||||
this.Options = bookmarkOptions;
|
||||
}
|
||||
|
||||
BookmarkOptions options;
|
||||
public BookmarkOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.options;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.options = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public Bookmark Bookmark
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "Options")]
|
||||
internal BookmarkOptions SerializedOptions
|
||||
{
|
||||
get { return this.Options; }
|
||||
set { this.Options = value; }
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback",
|
||||
Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
|
||||
[SecuritySafeCritical]
|
||||
public void Invoke(NativeActivityContext context, Bookmark bookmark, object value)
|
||||
{
|
||||
EnsureCallback(bookmarkCallbackType, bookmarkCallbackParameters);
|
||||
BookmarkCallback bookmarkCallback = (BookmarkCallback)this.Callback;
|
||||
bookmarkCallback(context, bookmark, value);
|
||||
}
|
||||
|
||||
public ActivityExecutionWorkItem CreateWorkItem(ActivityExecutor executor, bool isExternal, Bookmark bookmark, object value)
|
||||
{
|
||||
if (this.IsCallbackNull)
|
||||
{
|
||||
return executor.CreateEmptyWorkItem(this.ActivityInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BookmarkWorkItem(executor, isExternal, this, bookmark, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[DataContract]
|
||||
class BookmarkList : HybridCollection<Bookmark>
|
||||
{
|
||||
public BookmarkList()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
internal bool Contains(Bookmark bookmark)
|
||||
{
|
||||
if (this.SingleItem != null)
|
||||
{
|
||||
if (this.SingleItem.Equals(bookmark))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (this.MultipleItems != null)
|
||||
{
|
||||
for (int i = 0; i < this.MultipleItems.Count; i++)
|
||||
{
|
||||
if (bookmark.Equals(this.MultipleItems[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void TransferBookmarks(out Bookmark singleItem, out IList<Bookmark> multipleItems)
|
||||
{
|
||||
singleItem = base.SingleItem;
|
||||
multipleItems = base.MultipleItems;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Activities.Hosting;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[DataContract(Name = XD.Runtime.BookmarkManager, Namespace = XD.Runtime.Namespace)]
|
||||
class BookmarkManager
|
||||
{
|
||||
long nextId;
|
||||
|
||||
Dictionary<Bookmark, BookmarkCallbackWrapper> bookmarks;
|
||||
|
||||
BookmarkScope scope;
|
||||
|
||||
BookmarkScopeHandle scopeHandle;
|
||||
|
||||
public BookmarkManager()
|
||||
{
|
||||
this.nextId = 1;
|
||||
}
|
||||
|
||||
internal BookmarkManager(BookmarkScope scope, BookmarkScopeHandle scopeHandle)
|
||||
: this()
|
||||
{
|
||||
this.scope = scope;
|
||||
this.scopeHandle = scopeHandle;
|
||||
}
|
||||
|
||||
|
||||
public bool HasBookmarks
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.bookmarks != null && this.bookmarks.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "nextId")]
|
||||
internal long SerializedNextId
|
||||
{
|
||||
get { return this.nextId; }
|
||||
set { this.nextId = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "bookmarks")]
|
||||
internal Dictionary<Bookmark, BookmarkCallbackWrapper> SerializedBookmarks
|
||||
{
|
||||
get { return this.bookmarks; }
|
||||
set { this.bookmarks = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "scope")]
|
||||
internal BookmarkScope SerializedScope
|
||||
{
|
||||
get { return this.scope; }
|
||||
set { this.scope = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "scopeHandle")]
|
||||
internal BookmarkScopeHandle SerializedScopeHandle
|
||||
{
|
||||
get { return this.scopeHandle; }
|
||||
set { this.scopeHandle = value; }
|
||||
}
|
||||
|
||||
public Bookmark CreateBookmark(string name, BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
Bookmark toAdd = new Bookmark(name);
|
||||
|
||||
if (this.bookmarks != null && this.bookmarks.ContainsKey(toAdd))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.BookmarkAlreadyExists(name)));
|
||||
}
|
||||
|
||||
AddBookmark(toAdd, callback, owningInstance, options);
|
||||
//Regular bookmarks are never important
|
||||
UpdateAllExclusiveHandles(toAdd, owningInstance);
|
||||
|
||||
return toAdd;
|
||||
}
|
||||
|
||||
public Bookmark CreateBookmark(BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
Fx.Assert(this.scope == null, "We only support named bookmarks within bookmark scopes right now.");
|
||||
|
||||
Bookmark bookmark = Bookmark.Create(GetNextBookmarkId());
|
||||
AddBookmark(bookmark, callback, owningInstance, options);
|
||||
//Regular bookmarks are never important
|
||||
UpdateAllExclusiveHandles(bookmark, owningInstance);
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
void UpdateAllExclusiveHandles(Bookmark bookmark, ActivityInstance owningInstance)
|
||||
{
|
||||
Fx.Assert(bookmark != null, "Invalid call to UpdateAllExclusiveHandles. Bookmark was null");
|
||||
Fx.Assert(owningInstance != null, "Invalid call to UpdateAllExclusiveHandles. ActivityInstance was null");
|
||||
|
||||
if (owningInstance.PropertyManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!owningInstance.PropertyManager.HasExclusiveHandlesInScope)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ExclusiveHandle> handles = owningInstance.PropertyManager.FindAll<ExclusiveHandle>();
|
||||
|
||||
if (handles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < handles.Count; i++)
|
||||
{
|
||||
ExclusiveHandle handle = handles[i];
|
||||
if (handle != null)
|
||||
{
|
||||
if (this.scopeHandle != null)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (BookmarkScopeHandle bookmarkScopeHandle in handle.RegisteredBookmarkScopes)
|
||||
{
|
||||
if (bookmarkScopeHandle == this.scopeHandle)
|
||||
{
|
||||
handle.AddToImportantBookmarks(bookmark);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
handle.AddToUnimportantBookmarks(bookmark);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handle.AddToUnimportantBookmarks(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bookmark GenerateTempBookmark()
|
||||
{
|
||||
return Bookmark.Create(GetNextBookmarkId());
|
||||
}
|
||||
|
||||
void AddBookmark(Bookmark bookmark, BookmarkCallback callback, ActivityInstance owningInstance, BookmarkOptions options)
|
||||
{
|
||||
if (this.bookmarks == null)
|
||||
{
|
||||
this.bookmarks = new Dictionary<Bookmark, BookmarkCallbackWrapper>(Bookmark.Comparer);
|
||||
}
|
||||
|
||||
bookmark.Scope = this.scope;
|
||||
|
||||
BookmarkCallbackWrapper bookmarkCallbackWrapper = new BookmarkCallbackWrapper(callback, owningInstance, options)
|
||||
{
|
||||
Bookmark = bookmark
|
||||
};
|
||||
this.bookmarks.Add(bookmark, bookmarkCallbackWrapper);
|
||||
|
||||
owningInstance.AddBookmark(bookmark, options);
|
||||
|
||||
if (TD.CreateBookmarkIsEnabled())
|
||||
{
|
||||
TD.CreateBookmark(owningInstance.Activity.GetType().ToString(), owningInstance.Activity.DisplayName, owningInstance.Id, ActivityUtilities.GetTraceString(bookmark), ActivityUtilities.GetTraceString((BookmarkScope)bookmark.Scope));
|
||||
}
|
||||
}
|
||||
|
||||
long GetNextBookmarkId()
|
||||
{
|
||||
if (this.nextId == long.MaxValue)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new NotSupportedException(SR.OutOfInternalBookmarks));
|
||||
}
|
||||
|
||||
long result = this.nextId;
|
||||
this.nextId++;
|
||||
return result;
|
||||
}
|
||||
|
||||
// This method translates from a bookmark that we may have received from the outside world (IE - new Bookmark(someName))
|
||||
// to our internal Bookmark object. This is necessary because we use bookmark objects as the key to our dictionary
|
||||
// (hence our ability to resolve an externally created one), but we keep a lot of important information on our internal
|
||||
// instance of that bookmark. We must always perform this translation when doing exclusive handle housekeeping.
|
||||
public bool TryGetBookmarkFromInternalList(Bookmark bookmark, out Bookmark internalBookmark, out BookmarkCallbackWrapper callbackWrapper)
|
||||
{
|
||||
internalBookmark = null;
|
||||
callbackWrapper = null;
|
||||
if (this.bookmarks == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BookmarkCallbackWrapper wrapper;
|
||||
if (this.bookmarks.TryGetValue(bookmark, out wrapper))
|
||||
{
|
||||
internalBookmark = wrapper.Bookmark;
|
||||
callbackWrapper = wrapper;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public BookmarkResumptionResult TryGenerateWorkItem(ActivityExecutor executor, bool isExternal, ref Bookmark bookmark, object value, ActivityInstance isolationInstance, out ActivityExecutionWorkItem workItem)
|
||||
{
|
||||
Bookmark internalBookmark = null;
|
||||
BookmarkCallbackWrapper callbackWrapper = null;
|
||||
if (!this.TryGetBookmarkFromInternalList(bookmark, out internalBookmark, out callbackWrapper))
|
||||
{
|
||||
workItem = null;
|
||||
return BookmarkResumptionResult.NotFound;
|
||||
}
|
||||
|
||||
bookmark = internalBookmark;
|
||||
if (!ActivityUtilities.IsInScope(callbackWrapper.ActivityInstance, isolationInstance))
|
||||
{
|
||||
workItem = null;
|
||||
|
||||
// We know about the bookmark, but we can't resume it yet
|
||||
return BookmarkResumptionResult.NotReady;
|
||||
}
|
||||
|
||||
workItem = callbackWrapper.CreateWorkItem(executor, isExternal, bookmark, value);
|
||||
|
||||
if (!BookmarkOptionsHelper.SupportsMultipleResumes(callbackWrapper.Options))
|
||||
{
|
||||
// cleanup bookmark on resumption unless the user opts into multi-resume
|
||||
Remove(bookmark, callbackWrapper);
|
||||
}
|
||||
|
||||
return BookmarkResumptionResult.Success;
|
||||
}
|
||||
|
||||
public void PopulateBookmarkInfo(List<BookmarkInfo> bookmarks)
|
||||
{
|
||||
Fx.Assert(this.HasBookmarks, "Should only be called if this actually has bookmarks.");
|
||||
|
||||
foreach (KeyValuePair<Bookmark, BookmarkCallbackWrapper> bookmarkEntry in this.bookmarks)
|
||||
{
|
||||
if (bookmarkEntry.Key.IsNamed)
|
||||
{
|
||||
bookmarks.Add(bookmarkEntry.Key.GenerateBookmarkInfo(bookmarkEntry.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to translate using TryGetBookmarkFromInternalList because we already have
|
||||
// internal instances since this call comes from bookmarks hanging off of the
|
||||
// ActivityInstance and not from an external source
|
||||
public void PurgeBookmarks(Bookmark singleBookmark, IList<Bookmark> multipleBookmarks)
|
||||
{
|
||||
if (singleBookmark != null)
|
||||
{
|
||||
PurgeSingleBookmark(singleBookmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
Fx.Assert(multipleBookmarks != null, "caller should never pass null");
|
||||
for (int i = 0; i < multipleBookmarks.Count; i++)
|
||||
{
|
||||
Bookmark bookmark = multipleBookmarks[i];
|
||||
PurgeSingleBookmark(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void PurgeSingleBookmark(Bookmark bookmark)
|
||||
{
|
||||
Fx.Assert(this.bookmarks.ContainsKey(bookmark) && object.ReferenceEquals(bookmark, this.bookmarks[bookmark].Bookmark), "Something went wrong with our housekeeping - it must exist and must be our intenral reference");
|
||||
UpdateExclusiveHandleList(bookmark);
|
||||
this.bookmarks.Remove(bookmark);
|
||||
}
|
||||
|
||||
public bool Remove(Bookmark bookmark, ActivityInstance instanceAttemptingRemove)
|
||||
{
|
||||
// We need to translate to our internal instance of the bookmark. See TryGetBookmarkFromInternalList
|
||||
// for more details.
|
||||
BookmarkCallbackWrapper callbackWrapper;
|
||||
Bookmark internalBookmark;
|
||||
if (TryGetBookmarkFromInternalList(bookmark, out internalBookmark, out callbackWrapper))
|
||||
{
|
||||
if (callbackWrapper.ActivityInstance != instanceAttemptingRemove)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.OnlyBookmarkOwnerCanRemove));
|
||||
}
|
||||
|
||||
Remove(internalBookmark, callbackWrapper);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Remove(Bookmark bookmark, BookmarkCallbackWrapper callbackWrapper)
|
||||
{
|
||||
callbackWrapper.ActivityInstance.RemoveBookmark(bookmark, callbackWrapper.Options);
|
||||
UpdateExclusiveHandleList(bookmark);
|
||||
this.bookmarks.Remove(bookmark);
|
||||
}
|
||||
|
||||
void UpdateExclusiveHandleList(Bookmark bookmark)
|
||||
{
|
||||
if (bookmark.ExclusiveHandles != null)
|
||||
{
|
||||
for (int i = 0; i < bookmark.ExclusiveHandles.Count; i++)
|
||||
{
|
||||
ExclusiveHandle handle = bookmark.ExclusiveHandles[i];
|
||||
Fx.Assert(handle != null, "Internal error.. ExclusiveHandle was null");
|
||||
handle.RemoveBookmark(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Activities.Hosting;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[DataContract]
|
||||
class BookmarkWorkItem : ActivityExecutionWorkItem
|
||||
{
|
||||
BookmarkCallbackWrapper callbackWrapper;
|
||||
Bookmark bookmark;
|
||||
object state;
|
||||
|
||||
public BookmarkWorkItem(ActivityExecutor executor, bool isExternal, BookmarkCallbackWrapper callbackWrapper, Bookmark bookmark, object value)
|
||||
: this(callbackWrapper, bookmark, value)
|
||||
{
|
||||
if (isExternal)
|
||||
{
|
||||
executor.EnterNoPersist();
|
||||
this.ExitNoPersistRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This ctor is only used by subclasses which make their own determination about no persist or not
|
||||
protected BookmarkWorkItem(BookmarkCallbackWrapper callbackWrapper, Bookmark bookmark, object value)
|
||||
: base(callbackWrapper.ActivityInstance)
|
||||
{
|
||||
this.callbackWrapper = callbackWrapper;
|
||||
this.bookmark = bookmark;
|
||||
this.state = value;
|
||||
}
|
||||
|
||||
[DataMember(Name = "callbackWrapper")]
|
||||
internal BookmarkCallbackWrapper SerializedCallbackWrapper
|
||||
{
|
||||
get { return this.callbackWrapper; }
|
||||
set { this.callbackWrapper = value; }
|
||||
}
|
||||
|
||||
[DataMember(Name = "bookmark")]
|
||||
internal Bookmark SerializedBookmark
|
||||
{
|
||||
get { return this.bookmark; }
|
||||
set { this.bookmark = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "state")]
|
||||
internal object SerializedState
|
||||
{
|
||||
get { return this.state; }
|
||||
set { this.state = value; }
|
||||
}
|
||||
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
if (TD.CompleteBookmarkWorkItemIsEnabled())
|
||||
{
|
||||
TD.CompleteBookmarkWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, ActivityUtilities.GetTraceString(this.bookmark), ActivityUtilities.GetTraceString(this.bookmark.Scope));
|
||||
}
|
||||
}
|
||||
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
if (TD.ScheduleBookmarkWorkItemIsEnabled())
|
||||
{
|
||||
TD.ScheduleBookmarkWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, ActivityUtilities.GetTraceString(this.bookmark), ActivityUtilities.GetTraceString(this.bookmark.Scope));
|
||||
}
|
||||
}
|
||||
|
||||
public override void TraceStarting()
|
||||
{
|
||||
if (TD.StartBookmarkWorkItemIsEnabled())
|
||||
{
|
||||
TD.StartBookmarkWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, ActivityUtilities.GetTraceString(this.bookmark), ActivityUtilities.GetTraceString(this.bookmark.Scope));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
NativeActivityContext nativeContext = executor.NativeActivityContextPool.Acquire();
|
||||
|
||||
try
|
||||
{
|
||||
nativeContext.Initialize(this.ActivityInstance, executor, bookmarkManager);
|
||||
this.callbackWrapper.Invoke(nativeContext, this.bookmark, this.state);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
this.ExceptionToPropagate = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
nativeContext.Dispose();
|
||||
executor.NativeActivityContextPool.Release(nativeContext);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
|
||||
[DataContract]
|
||||
class CallbackWrapper
|
||||
{
|
||||
static BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static;
|
||||
|
||||
static PermissionSet ReflectionMemberAccessPermissionSet = null;
|
||||
|
||||
string callbackName;
|
||||
|
||||
string declaringAssemblyName;
|
||||
|
||||
string declaringTypeName;
|
||||
|
||||
Delegate callback;
|
||||
|
||||
ActivityInstance activityInstance;
|
||||
|
||||
public CallbackWrapper(Delegate callback, ActivityInstance owningInstance)
|
||||
{
|
||||
this.ActivityInstance = owningInstance;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public ActivityInstance ActivityInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityInstance;
|
||||
}
|
||||
private set
|
||||
{
|
||||
this.activityInstance = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool IsCallbackNull
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.callback == null && this.callbackName == null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Delegate Callback
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.callback;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "callbackName")]
|
||||
internal string SerializedCallbackName
|
||||
{
|
||||
get { return this.callbackName; }
|
||||
set { this.callbackName = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "declaringAssemblyName")]
|
||||
internal string SerializedDeclaringAssemblyName
|
||||
{
|
||||
get { return this.declaringAssemblyName; }
|
||||
set { this.declaringAssemblyName = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "declaringTypeName")]
|
||||
internal string SerializedDeclaringTypeName
|
||||
{
|
||||
get { return this.declaringTypeName; }
|
||||
set { this.declaringTypeName = value; }
|
||||
}
|
||||
|
||||
[DataMember(Name = "ActivityInstance")]
|
||||
internal ActivityInstance SerializedActivityInstance
|
||||
{
|
||||
get { return this.ActivityInstance; }
|
||||
set { this.ActivityInstance = value; }
|
||||
}
|
||||
|
||||
public static bool IsValidCallback(Delegate callback, ActivityInstance owningInstance)
|
||||
{
|
||||
Fx.Assert(callback != null, "This should only be called with non-null callbacks");
|
||||
|
||||
object target = callback.Target;
|
||||
|
||||
// if the target is null, it is static
|
||||
if (target == null)
|
||||
{
|
||||
Fx.Assert(callback.Method.IsStatic, "This method should be static when target is null");
|
||||
return true;
|
||||
}
|
||||
|
||||
// its owner's activity
|
||||
if (object.ReferenceEquals(target, owningInstance.Activity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special note about establishing callbacks:
|
||||
//
|
||||
// When establising a callback, we need to Assert ReflectionPermission(MemberAccess) because the callback
|
||||
// method will typically be a private method within a class that derives from Activity. Activity authors need
|
||||
// to be aware that their callback may be invoked with different permissions than were present when the Activity
|
||||
// was originally executed and perform appropriate security checks.
|
||||
//
|
||||
// We ensure that the declaring type of the callback method derives from Activity. This check is made in RecreateCallback.
|
||||
//
|
||||
// The classes that derive from CallbackWrapper and call EnsureCallback do an explicit cast of the returned delegate
|
||||
// to the delegate type that they expect before calling thru to the delegate. This cast is done in SecuritySafeCritical code.
|
||||
//
|
||||
// These checks are both made in Security[Safe]Critical code.
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling GenerateCallback, which are SecurityCritical.")]
|
||||
[SecurityCritical]
|
||||
protected void EnsureCallback(Type delegateType, Type[] parameterTypes, Type genericParameter)
|
||||
{
|
||||
// We were unloaded and have some work to do to rebuild the callback
|
||||
if (this.callback == null)
|
||||
{
|
||||
this.callback = GenerateCallback(delegateType, parameterTypes, genericParameter);
|
||||
Fx.Assert(this.callback != null, "GenerateCallback should have been able to produce a non-null callback.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling GenerateCallback, which are SecurityCritical.",
|
||||
Safe = "Because the delegate is not leaked out of this routine. It is only validated.")]
|
||||
[SecuritySafeCritical]
|
||||
protected void ValidateCallbackResolution(Type delegateType, Type[] parameterTypes, Type genericParameter)
|
||||
{
|
||||
Fx.Assert(this.callback != null && this.callbackName != null, "We must have a callback and a callback name");
|
||||
|
||||
if (!this.callback.Equals(GenerateCallback(delegateType, parameterTypes, genericParameter)))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidExecutionCallback(this.callback.Method, null)));
|
||||
}
|
||||
}
|
||||
|
||||
MethodInfo FindMatchingGenericMethod(Type declaringType, Type[] parameterTypes, Type genericParameter)
|
||||
{
|
||||
MethodInfo[] potentialMatches = declaringType.GetMethods(bindingFlags);
|
||||
for (int i = 0; i < potentialMatches.Length; i++)
|
||||
{
|
||||
MethodInfo potentialMatch = potentialMatches[i];
|
||||
|
||||
if (potentialMatch.IsGenericMethod && potentialMatch.Name == this.callbackName)
|
||||
{
|
||||
Fx.Assert(potentialMatch.IsGenericMethodDefinition, "We should be getting the generic method definition here.");
|
||||
|
||||
Type[] genericArguments = potentialMatch.GetGenericArguments();
|
||||
|
||||
if (genericArguments.Length == 1)
|
||||
{
|
||||
potentialMatch = potentialMatch.MakeGenericMethod(genericParameter);
|
||||
|
||||
ParameterInfo[] parameters = potentialMatch.GetParameters();
|
||||
|
||||
bool match = true;
|
||||
for (int parameterIndex = 0; parameterIndex < parameters.Length; parameterIndex++)
|
||||
{
|
||||
ParameterInfo parameter = parameters[parameterIndex];
|
||||
|
||||
if (parameter.IsOut || parameter.IsOptional || parameter.ParameterType != parameterTypes[parameterIndex])
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
return potentialMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling RecreateCallback, which is SecurityCritical.")]
|
||||
[SecurityCritical]
|
||||
Delegate GenerateCallback(Type delegateType, Type[] parameterTypes, Type genericParameter)
|
||||
{
|
||||
Type declaringType;
|
||||
MethodInfo methodInfo = GetMatchingMethod(parameterTypes, out declaringType);
|
||||
|
||||
if (methodInfo == null)
|
||||
{
|
||||
Fx.Assert(declaringType != null, "We must have found the declaring type.");
|
||||
methodInfo = FindMatchingGenericMethod(declaringType, parameterTypes, genericParameter);
|
||||
}
|
||||
|
||||
if (methodInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return RecreateCallback(delegateType, methodInfo);
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling RecreateCallback, which is SecurityCritical.")]
|
||||
[SecurityCritical]
|
||||
protected void EnsureCallback(Type delegateType, Type[] parameters)
|
||||
{
|
||||
// We were unloaded and have some work to do to rebuild the callback
|
||||
if (this.callback == null)
|
||||
{
|
||||
Type unusedDeclaringType;
|
||||
MethodInfo methodInfo = GetMatchingMethod(parameters, out unusedDeclaringType);
|
||||
|
||||
Fx.Assert(methodInfo != null, "We must have a method info by now");
|
||||
|
||||
this.callback = RecreateCallback(delegateType, methodInfo);
|
||||
}
|
||||
}
|
||||
|
||||
MethodInfo GetMatchingMethod(Type[] parameters, out Type declaringType)
|
||||
{
|
||||
Fx.Assert(this.callbackName != null, "This should only be called when there is actually a callback to run.");
|
||||
|
||||
object targetInstance = this.ActivityInstance.Activity;
|
||||
|
||||
if (this.declaringTypeName == null)
|
||||
{
|
||||
declaringType = targetInstance.GetType();
|
||||
}
|
||||
else
|
||||
{
|
||||
// make a MethodInfo since it's not hanging directly off of our activity type
|
||||
Assembly callbackAssembly;
|
||||
if (this.declaringAssemblyName != null)
|
||||
{
|
||||
callbackAssembly = Assembly.Load(this.declaringAssemblyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
callbackAssembly = targetInstance.GetType().Assembly;
|
||||
}
|
||||
|
||||
declaringType = callbackAssembly.GetType(this.declaringTypeName);
|
||||
}
|
||||
|
||||
Fx.Assert(declaringType != null, "declaring type should be re-constructable from our serialized components");
|
||||
|
||||
return declaringType.GetMethod(this.callbackName, bindingFlags, null, parameters, null);
|
||||
}
|
||||
|
||||
// The MethodInfo passed to this method must be derived
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are Asserting ReflectionPermission(MemberAccess) in order to get at private callback methods.")]
|
||||
[SecurityCritical]
|
||||
Delegate RecreateCallback(Type delegateType, MethodInfo callbackMethod)
|
||||
{
|
||||
object targetInstance = null;
|
||||
|
||||
// If the declaring type does not derive from Activity, somebody has manipulated the callback in the persistece store.
|
||||
if (!typeof(Activity).IsAssignableFrom(callbackMethod.DeclaringType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!callbackMethod.IsStatic)
|
||||
{
|
||||
targetInstance = this.ActivityInstance.Activity;
|
||||
}
|
||||
|
||||
// Asserting ReflectionPermission.MemberAccess because the callback method is most likely internal or private
|
||||
if (ReflectionMemberAccessPermissionSet == null)
|
||||
{
|
||||
PermissionSet myPermissionSet = new PermissionSet(PermissionState.None);
|
||||
myPermissionSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
|
||||
Interlocked.CompareExchange(ref ReflectionMemberAccessPermissionSet, myPermissionSet, null);
|
||||
}
|
||||
ReflectionMemberAccessPermissionSet.Assert();
|
||||
try
|
||||
{
|
||||
return Delegate.CreateDelegate(delegateType, targetInstance, callbackMethod);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CodeAccessPermission.RevertAssert();
|
||||
}
|
||||
}
|
||||
|
||||
[OnSerializing]
|
||||
[SuppressMessage(FxCop.Category.Usage, FxCop.Rule.ReviewUnusedParameters)]
|
||||
[SuppressMessage(FxCop.Category.Usage, "CA2238:ImplementSerializationMethodsCorrectly",
|
||||
Justification = "Needs to be internal for serialization in partial trust. We have set InternalsVisibleTo(System.Runtime.Serialization) to allow this.")]
|
||||
internal void OnSerializing(StreamingContext context)
|
||||
{
|
||||
if (this.callbackName == null && !this.IsCallbackNull)
|
||||
{
|
||||
MethodInfo method = this.callback.Method;
|
||||
this.callbackName = method.Name;
|
||||
Type declaringType = method.DeclaringType;
|
||||
Type activityType = this.ActivityInstance.Activity.GetType();
|
||||
|
||||
if (declaringType != activityType)
|
||||
{
|
||||
// If we're not directly off of the Activity type being used,
|
||||
// then we need to store the declaringType's name.
|
||||
this.declaringTypeName = declaringType.FullName;
|
||||
|
||||
if (declaringType.Assembly != activityType.Assembly)
|
||||
{
|
||||
this.declaringAssemblyName = declaringType.Assembly.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
if (method.IsGenericMethod)
|
||||
{
|
||||
OnSerializingGenericCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnSerializingGenericCallback()
|
||||
{
|
||||
// Generics are invalid by default
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidExecutionCallback(this.callback.Method, null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// <copyright file="CollapseTemporaryResolutionLocationWorkItem.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System.Activities.Tracking;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
[DataContract]
|
||||
internal class CollapseTemporaryResolutionLocationWorkItem : WorkItem
|
||||
{
|
||||
private Location location;
|
||||
|
||||
public CollapseTemporaryResolutionLocationWorkItem(Location location, ActivityInstance instance)
|
||||
: base(instance)
|
||||
{
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public override bool IsValid
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override ActivityInstance PropertyManagerOwner
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "location")]
|
||||
internal Location SerializedLocation
|
||||
{
|
||||
get { return this.location; }
|
||||
set { this.location = value; }
|
||||
}
|
||||
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
TraceRuntimeWorkItemScheduled();
|
||||
}
|
||||
|
||||
public override void TraceStarting()
|
||||
{
|
||||
TraceRuntimeWorkItemStarting();
|
||||
}
|
||||
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
TraceRuntimeWorkItemCompleted();
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
this.location.TemporaryResolutionEnvironment.CollapseTemporaryResolutionLocation(this.location);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void PostProcess(ActivityExecutor executor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[DataContract]
|
||||
class CompletionBookmark
|
||||
{
|
||||
CompletionCallbackWrapper callbackWrapper;
|
||||
|
||||
public CompletionBookmark()
|
||||
{
|
||||
// Called when we want to use the special completion callback
|
||||
}
|
||||
|
||||
public CompletionBookmark(CompletionCallbackWrapper callbackWrapper)
|
||||
{
|
||||
this.callbackWrapper = callbackWrapper;
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "callbackWrapper")]
|
||||
internal CompletionCallbackWrapper SerializedCallbackWrapper
|
||||
{
|
||||
get { return this.callbackWrapper; }
|
||||
set { this.callbackWrapper = value; }
|
||||
}
|
||||
|
||||
public void CheckForCancelation()
|
||||
{
|
||||
Fx.Assert(this.callbackWrapper != null, "We must have a callback wrapper if we are calling this.");
|
||||
this.callbackWrapper.CheckForCancelation();
|
||||
}
|
||||
|
||||
public WorkItem GenerateWorkItem(ActivityInstance completedInstance, ActivityExecutor executor)
|
||||
{
|
||||
if (this.callbackWrapper != null)
|
||||
{
|
||||
return this.callbackWrapper.CreateWorkItem(completedInstance, executor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Variable defaults and argument expressions always have a parent
|
||||
// and never have a CompletionBookmark
|
||||
if (completedInstance.State != ActivityInstanceState.Closed && completedInstance.Parent.HasNotExecuted)
|
||||
{
|
||||
completedInstance.Parent.SetInitializationIncomplete();
|
||||
}
|
||||
|
||||
return new EmptyWithCancelationCheckWorkItem(completedInstance.Parent, completedInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Activities.DynamicUpdate;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security;
|
||||
|
||||
// can't add FuncCompletionCallbackWrapper<T> since we don't know what to close the generic with
|
||||
[KnownType(typeof(ActivityCompletionCallbackWrapper))]
|
||||
[KnownType(typeof(DelegateCompletionCallbackWrapper))]
|
||||
[DataContract]
|
||||
abstract class CompletionCallbackWrapper : CallbackWrapper
|
||||
{
|
||||
static Type completionCallbackType = typeof(CompletionCallback);
|
||||
static Type[] completionCallbackParameters = new Type[] { typeof(NativeActivityContext), typeof(ActivityInstance) };
|
||||
|
||||
bool checkForCancelation;
|
||||
|
||||
bool needsToGatherOutputs;
|
||||
|
||||
protected CompletionCallbackWrapper(Delegate callback, ActivityInstance owningInstance)
|
||||
: base(callback, owningInstance)
|
||||
{
|
||||
}
|
||||
|
||||
protected bool NeedsToGatherOutputs
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.needsToGatherOutputs;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.needsToGatherOutputs = value;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "checkForCancelation")]
|
||||
internal bool SerializedCheckForCancelation
|
||||
{
|
||||
get { return this.checkForCancelation; }
|
||||
set { this.checkForCancelation = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "needsToGatherOutputs")]
|
||||
internal bool SerializedNeedsToGatherOutputs
|
||||
{
|
||||
get { return this.needsToGatherOutputs; }
|
||||
set { this.needsToGatherOutputs = value; }
|
||||
}
|
||||
|
||||
public void CheckForCancelation()
|
||||
{
|
||||
this.checkForCancelation = true;
|
||||
}
|
||||
|
||||
protected virtual void GatherOutputs(ActivityInstance completedInstance)
|
||||
{
|
||||
// No-op in the base class
|
||||
}
|
||||
|
||||
internal WorkItem CreateWorkItem(ActivityInstance completedInstance, ActivityExecutor executor)
|
||||
{
|
||||
// We use the property to guard against the virtual method call
|
||||
// since we don't need it in the common case
|
||||
if (this.NeedsToGatherOutputs)
|
||||
{
|
||||
this.GatherOutputs(completedInstance);
|
||||
}
|
||||
|
||||
CompletionWorkItem workItem;
|
||||
|
||||
if (this.checkForCancelation)
|
||||
{
|
||||
workItem = new CompletionWithCancelationCheckWorkItem(this, completedInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
workItem = executor.CompletionWorkItemPool.Acquire();
|
||||
workItem.Initialize(this, completedInstance);
|
||||
}
|
||||
|
||||
if (completedInstance.InstanceMap != null)
|
||||
{
|
||||
completedInstance.InstanceMap.AddEntry(workItem);
|
||||
}
|
||||
|
||||
return workItem;
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because any implementation will be calling EnsureCallback",
|
||||
Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
|
||||
[SecuritySafeCritical]
|
||||
protected internal abstract void Invoke(NativeActivityContext context, ActivityInstance completedInstance);
|
||||
|
||||
[DataContract]
|
||||
public class CompletionWorkItem : ActivityExecutionWorkItem, ActivityInstanceMap.IActivityReference
|
||||
{
|
||||
CompletionCallbackWrapper callbackWrapper;
|
||||
ActivityInstance completedInstance;
|
||||
|
||||
// Called by the Pool.
|
||||
public CompletionWorkItem()
|
||||
{
|
||||
this.IsPooled = true;
|
||||
}
|
||||
|
||||
// Only used by non-pooled base classes.
|
||||
protected CompletionWorkItem(CompletionCallbackWrapper callbackWrapper, ActivityInstance completedInstance)
|
||||
: base(callbackWrapper.ActivityInstance)
|
||||
{
|
||||
this.callbackWrapper = callbackWrapper;
|
||||
this.completedInstance = completedInstance;
|
||||
}
|
||||
|
||||
protected ActivityInstance CompletedInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.completedInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember(Name = "callbackWrapper")]
|
||||
internal CompletionCallbackWrapper SerializedCallbackWrapper
|
||||
{
|
||||
get { return this.callbackWrapper; }
|
||||
set { this.callbackWrapper = value; }
|
||||
}
|
||||
|
||||
[DataMember(Name = "completedInstance")]
|
||||
internal ActivityInstance SerializedCompletedInstance
|
||||
{
|
||||
get { return this.completedInstance; }
|
||||
set { this.completedInstance = value; }
|
||||
}
|
||||
|
||||
public void Initialize(CompletionCallbackWrapper callbackWrapper, ActivityInstance completedInstance)
|
||||
{
|
||||
base.Reinitialize(callbackWrapper.ActivityInstance);
|
||||
this.callbackWrapper = callbackWrapper;
|
||||
this.completedInstance = completedInstance;
|
||||
}
|
||||
|
||||
protected override void ReleaseToPool(ActivityExecutor executor)
|
||||
{
|
||||
base.ClearForReuse();
|
||||
this.callbackWrapper = null;
|
||||
this.completedInstance = null;
|
||||
|
||||
executor.CompletionWorkItemPool.Release(this);
|
||||
}
|
||||
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
if (TD.CompleteCompletionWorkItemIsEnabled())
|
||||
{
|
||||
TD.CompleteCompletionWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.completedInstance.Activity.GetType().ToString(), this.completedInstance.Activity.DisplayName, this.completedInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
if (TD.ScheduleCompletionWorkItemIsEnabled())
|
||||
{
|
||||
TD.ScheduleCompletionWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.completedInstance.Activity.GetType().ToString(), this.completedInstance.Activity.DisplayName, this.completedInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public override void TraceStarting()
|
||||
{
|
||||
if (TD.StartCompletionWorkItemIsEnabled())
|
||||
{
|
||||
TD.StartCompletionWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.completedInstance.Activity.GetType().ToString(), this.completedInstance.Activity.DisplayName, this.completedInstance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
NativeActivityContext context = executor.NativeActivityContextPool.Acquire();
|
||||
|
||||
Fx.Assert(this.completedInstance.Activity != null, "Activity definition should always be associated with an activity instance.");
|
||||
|
||||
try
|
||||
{
|
||||
context.Initialize(this.ActivityInstance, executor, bookmarkManager);
|
||||
this.callbackWrapper.Invoke(context, this.completedInstance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
this.ExceptionToPropagate = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Dispose();
|
||||
executor.NativeActivityContextPool.Release(context);
|
||||
|
||||
if (this.ActivityInstance.InstanceMap != null)
|
||||
{
|
||||
this.ActivityInstance.InstanceMap.RemoveEntry(this);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Activity ActivityInstanceMap.IActivityReference.Activity
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.completedInstance.Activity;
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityInstanceMap.IActivityReference.Load(Activity activity, ActivityInstanceMap instanceMap)
|
||||
{
|
||||
if (this.completedInstance.Activity == null)
|
||||
{
|
||||
((ActivityInstanceMap.IActivityReference)this.completedInstance).Load(activity, instanceMap);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
class CompletionWithCancelationCheckWorkItem : CompletionWorkItem
|
||||
{
|
||||
public CompletionWithCancelationCheckWorkItem(CompletionCallbackWrapper callbackWrapper, ActivityInstance completedInstance)
|
||||
: base(callbackWrapper, completedInstance)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
if (this.CompletedInstance.State != ActivityInstanceState.Closed && this.ActivityInstance.IsPerformingDefaultCancelation)
|
||||
{
|
||||
this.ActivityInstance.MarkCanceled();
|
||||
}
|
||||
|
||||
return base.Execute(executor, bookmarkManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security;
|
||||
|
||||
[DataContract]
|
||||
class DelegateCompletionCallbackWrapper : CompletionCallbackWrapper
|
||||
{
|
||||
static readonly Type callbackType = typeof(DelegateCompletionCallback);
|
||||
static readonly Type[] callbackParameterTypes = new Type[] { typeof(NativeActivityContext), typeof(ActivityInstance), typeof(IDictionary<string, object>) };
|
||||
|
||||
Dictionary<string, object> results;
|
||||
|
||||
public DelegateCompletionCallbackWrapper(DelegateCompletionCallback callback, ActivityInstance owningInstance)
|
||||
: base(callback, owningInstance)
|
||||
{
|
||||
this.NeedsToGatherOutputs = true;
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "results")]
|
||||
internal Dictionary<string, object> SerializedResults
|
||||
{
|
||||
get { return this.results; }
|
||||
set { this.results = value; }
|
||||
}
|
||||
|
||||
protected override void GatherOutputs(ActivityInstance completedInstance)
|
||||
{
|
||||
if (completedInstance.Activity.HandlerOf != null)
|
||||
{
|
||||
IList<RuntimeDelegateArgument> runtimeArguments = completedInstance.Activity.HandlerOf.RuntimeDelegateArguments;
|
||||
LocationEnvironment environment = completedInstance.Environment;
|
||||
|
||||
for (int i = 0; i < runtimeArguments.Count; i++)
|
||||
{
|
||||
RuntimeDelegateArgument runtimeArgument = runtimeArguments[i];
|
||||
|
||||
if (runtimeArgument.BoundArgument != null)
|
||||
{
|
||||
if (ArgumentDirectionHelper.IsOut(runtimeArgument.Direction))
|
||||
{
|
||||
Location parameterLocation = environment.GetSpecificLocation(runtimeArgument.BoundArgument.Id);
|
||||
|
||||
if (parameterLocation != null)
|
||||
{
|
||||
if (this.results == null)
|
||||
{
|
||||
this.results = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
this.results.Add(runtimeArgument.Name, parameterLocation.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback",
|
||||
Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
|
||||
[SecuritySafeCritical]
|
||||
protected internal override void Invoke(NativeActivityContext context, ActivityInstance completedInstance)
|
||||
{
|
||||
EnsureCallback(callbackType, callbackParameterTypes);
|
||||
DelegateCompletionCallback completionCallback = (DelegateCompletionCallback)this.Callback;
|
||||
|
||||
IDictionary<string, object> returnValue = this.results;
|
||||
|
||||
if (returnValue == null)
|
||||
{
|
||||
returnValue = ActivityUtilities.EmptyParameters;
|
||||
}
|
||||
|
||||
completionCallback(context, completedInstance, returnValue);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[DataContract]
|
||||
class EmptyWithCancelationCheckWorkItem : ActivityExecutionWorkItem
|
||||
{
|
||||
ActivityInstance completedInstance;
|
||||
|
||||
public EmptyWithCancelationCheckWorkItem(ActivityInstance activityInstance, ActivityInstance completedInstance)
|
||||
: base(activityInstance)
|
||||
{
|
||||
this.completedInstance = completedInstance;
|
||||
this.IsEmpty = true;
|
||||
}
|
||||
|
||||
[DataMember(Name = "completedInstance")]
|
||||
internal ActivityInstance SerializedCompletedInstance
|
||||
{
|
||||
get { return this.completedInstance; }
|
||||
set { this.completedInstance = value; }
|
||||
}
|
||||
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
TraceRuntimeWorkItemCompleted();
|
||||
}
|
||||
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
TraceRuntimeWorkItemScheduled();
|
||||
}
|
||||
|
||||
public override void TraceStarting()
|
||||
{
|
||||
TraceRuntimeWorkItemStarting();
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
Fx.Assert("Empty work items should never been executed.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void PostProcess(ActivityExecutor executor)
|
||||
{
|
||||
if (this.completedInstance.State != ActivityInstanceState.Closed && this.ActivityInstance.IsPerformingDefaultCancelation)
|
||||
{
|
||||
this.ActivityInstance.MarkCanceled();
|
||||
}
|
||||
|
||||
base.PostProcess(executor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
|
||||
[DataContract]
|
||||
class EmptyWorkItem : ActivityExecutionWorkItem
|
||||
{
|
||||
// Called by the Pool.
|
||||
public EmptyWorkItem()
|
||||
{
|
||||
this.IsPooled = true;
|
||||
|
||||
// Empty doesn't need to be cleared/reinitialized so we set it here
|
||||
this.IsEmpty = true;
|
||||
}
|
||||
|
||||
public void Initialize(ActivityInstance activityInstance)
|
||||
{
|
||||
base.Reinitialize(activityInstance);
|
||||
}
|
||||
|
||||
protected override void ReleaseToPool(ActivityExecutor executor)
|
||||
{
|
||||
base.ClearForReuse();
|
||||
|
||||
executor.EmptyWorkItemPool.Release(this);
|
||||
}
|
||||
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
TraceRuntimeWorkItemCompleted();
|
||||
}
|
||||
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
TraceRuntimeWorkItemScheduled();
|
||||
}
|
||||
|
||||
public override void TraceStarting()
|
||||
{
|
||||
TraceRuntimeWorkItemStarting();
|
||||
}
|
||||
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
Fx.Assert("Empty work items should never been executed.");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[DataContract]
|
||||
class ExclusiveHandleList : HybridCollection<ExclusiveHandle>
|
||||
{
|
||||
public ExclusiveHandleList()
|
||||
: base() { }
|
||||
|
||||
internal bool Contains(ExclusiveHandle handle)
|
||||
{
|
||||
if (this.SingleItem != null)
|
||||
{
|
||||
if (this.SingleItem.Equals(handle))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (this.MultipleItems != null)
|
||||
{
|
||||
for (int i = 0; i < this.MultipleItems.Count; i++)
|
||||
{
|
||||
if (handle.Equals(this.MultipleItems[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
// <copyright file="ExecuteSynchronousExpressionWorkItem.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
namespace System.Activities.Runtime
|
||||
{
|
||||
using System.Activities.Tracking;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates a new-fast-path (SkipArgumentsResolution and Not UseOldFastPath) expression
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
internal class ExecuteSynchronousExpressionWorkItem : ActivityExecutionWorkItem, ActivityInstanceMap.IActivityReference
|
||||
{
|
||||
private ActivityWithResult expressionActivity;
|
||||
|
||||
private long instanceId;
|
||||
|
||||
private ResolveNextArgumentWorkItem nextArgumentWorkItem;
|
||||
|
||||
private Location resultLocation;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ExecuteSynchronousExpressionWorkItem class.
|
||||
/// Called by the pool.
|
||||
/// </summary>
|
||||
public ExecuteSynchronousExpressionWorkItem()
|
||||
{
|
||||
this.IsPooled = true;
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "instanceId")]
|
||||
internal long SerializedInstanceId
|
||||
{
|
||||
get { return this.instanceId; }
|
||||
set { this.instanceId = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "nextArgumentWorkItem")]
|
||||
internal ResolveNextArgumentWorkItem SerializedNextArgumentWorkItem
|
||||
{
|
||||
get { return this.nextArgumentWorkItem; }
|
||||
set { this.nextArgumentWorkItem = value; }
|
||||
}
|
||||
|
||||
[DataMember(EmitDefaultValue = false, Name = "resultLocation")]
|
||||
internal Location SerializedResultLocation
|
||||
{
|
||||
get { return this.resultLocation; }
|
||||
set { this.resultLocation = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Activity reference to serialize at persistence
|
||||
/// </summary>
|
||||
Activity ActivityInstanceMap.IActivityReference.Activity
|
||||
{
|
||||
get { return this.expressionActivity; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called each time a work item is acquired from the pool
|
||||
/// </summary>
|
||||
/// <param name="parentInstance">The ActivityInstance containin the variable or argument that contains this expression</param>
|
||||
/// <param name="expressionActivity">The expression to evaluate</param>
|
||||
/// <param name="instanceId">The ActivityInstanceID to use for expressionActivity</param>
|
||||
/// <param name="resultLocation">Location where the result of expressionActivity should be placed</param>
|
||||
/// <param name="nextArgumentWorkItem">WorkItem to execute after this one</param>
|
||||
public void Initialize(ActivityInstance parentInstance, ActivityWithResult expressionActivity, long instanceId, Location resultLocation, ResolveNextArgumentWorkItem nextArgumentWorkItem)
|
||||
{
|
||||
this.Reinitialize(parentInstance);
|
||||
|
||||
Fx.Assert(resultLocation != null, "We should only use this work item when we are resolving arguments/variables and therefore have a result location.");
|
||||
Fx.Assert(expressionActivity.IsFastPath, "Should only use this work item for fast path expressions");
|
||||
|
||||
this.expressionActivity = expressionActivity;
|
||||
this.instanceId = instanceId;
|
||||
this.resultLocation = resultLocation;
|
||||
this.nextArgumentWorkItem = nextArgumentWorkItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trace when we're scheduled
|
||||
/// </summary>
|
||||
public override void TraceScheduled()
|
||||
{
|
||||
TraceRuntimeWorkItemScheduled();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trace when we start
|
||||
/// </summary>
|
||||
public override void TraceStarting()
|
||||
{
|
||||
TraceRuntimeWorkItemStarting();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trace when we complete
|
||||
/// </summary>
|
||||
public override void TraceCompleted()
|
||||
{
|
||||
TraceRuntimeWorkItemCompleted();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the work item
|
||||
/// </summary>
|
||||
/// <param name="executor">The executor</param>
|
||||
/// <param name="bookmarkManager">The bookmark manager</param>
|
||||
/// <returns>True to continue executing work items, false to yield the thread</returns>
|
||||
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
|
||||
{
|
||||
ActivityInfo activityInfo = null;
|
||||
this.TrackExecuting(executor, ref activityInfo);
|
||||
|
||||
try
|
||||
{
|
||||
executor.ExecuteInResolutionContextUntyped(this.ActivityInstance, this.expressionActivity, this.instanceId, this.resultLocation);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
this.TrackFaulted(executor, ref activityInfo);
|
||||
|
||||
if (this.nextArgumentWorkItem != null)
|
||||
{
|
||||
executor.ScheduleItem(this.nextArgumentWorkItem);
|
||||
}
|
||||
|
||||
executor.ScheduleExpressionFaultPropagation(this.expressionActivity, this.instanceId, this.ActivityInstance, e);
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (this.ActivityInstance.InstanceMap != null)
|
||||
{
|
||||
this.ActivityInstance.InstanceMap.RemoveEntry(this);
|
||||
}
|
||||
}
|
||||
|
||||
this.TrackClosed(executor, ref activityInfo);
|
||||
|
||||
if (this.nextArgumentWorkItem != null)
|
||||
{
|
||||
this.EvaluateNextArgument(executor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix up activity reference after persistence
|
||||
/// </summary>
|
||||
/// <param name="activity">The persisted activity reference</param>
|
||||
/// <param name="instanceMap">The map containing persisted activity references</param>
|
||||
void ActivityInstanceMap.IActivityReference.Load(Activity activity, ActivityInstanceMap instanceMap)
|
||||
{
|
||||
ActivityWithResult activityWithResult = activity as ActivityWithResult;
|
||||
if (activityWithResult == null)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(
|
||||
new ValidationException(SR.ActivityTypeMismatch(activity.DisplayName, typeof(ActivityWithResult).Name)));
|
||||
}
|
||||
|
||||
this.expressionActivity = activityWithResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release work item back to pool
|
||||
/// </summary>
|
||||
/// <param name="executor">Executor that owns the work item.</param>
|
||||
protected override void ReleaseToPool(ActivityExecutor executor)
|
||||
{
|
||||
this.ClearForReuse();
|
||||
|
||||
this.expressionActivity = null;
|
||||
this.instanceId = 0;
|
||||
this.resultLocation = null;
|
||||
this.nextArgumentWorkItem = null;
|
||||
|
||||
executor.ExecuteSynchronousExpressionWorkItemPool.Release(this);
|
||||
}
|
||||
|
||||
private void EvaluateNextArgument(ActivityExecutor executor)
|
||||
{
|
||||
if (executor.HasPendingTrackingRecords && this.nextArgumentWorkItem.CanExecuteUserCode())
|
||||
{
|
||||
// Need to schedule a separate work item so we flush tracking before we continue.
|
||||
// This ensures consistent ordering of tracking output and user code.
|
||||
executor.ScheduleItem(this.nextArgumentWorkItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
executor.ExecuteSynchronousWorkItem(this.nextArgumentWorkItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureActivityInfo(ref ActivityInfo activityInfo)
|
||||
{
|
||||
if (activityInfo == null)
|
||||
{
|
||||
activityInfo = new ActivityInfo(this.expressionActivity, this.instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
private void TrackClosed(ActivityExecutor executor, ref ActivityInfo activityInfo)
|
||||
{
|
||||
if (executor.ShouldTrackActivityStateRecordsClosedState)
|
||||
{
|
||||
this.TrackState(executor, ActivityInstanceState.Closed, ref activityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void TrackExecuting(ActivityExecutor executor, ref ActivityInfo activityInfo)
|
||||
{
|
||||
if (executor.ShouldTrackActivityStateRecordsExecutingState)
|
||||
{
|
||||
this.TrackState(executor, ActivityInstanceState.Executing, ref activityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void TrackFaulted(ActivityExecutor executor, ref ActivityInfo activityInfo)
|
||||
{
|
||||
if (executor.ShouldTrackActivityStateRecords)
|
||||
{
|
||||
this.TrackState(executor, ActivityInstanceState.Faulted, ref activityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void TrackState(ActivityExecutor executor, ActivityInstanceState state, ref ActivityInfo activityInfo)
|
||||
{
|
||||
if (executor.ShouldTrackActivity(this.expressionActivity.DisplayName))
|
||||
{
|
||||
this.EnsureActivityInfo(ref activityInfo);
|
||||
executor.AddTrackingRecord(new ActivityStateRecord(executor.WorkflowInstanceId, activityInfo, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user