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

View File

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

View File

@@ -0,0 +1 @@
b9cf8fe7e52450ceff6d1c34154cba802c4c505e

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More