191 lines
6.7 KiB
C#
191 lines
6.7 KiB
C#
|
//----------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------
|
||
|
namespace System.Activities.Statements
|
||
|
{
|
||
|
using System;
|
||
|
using System.Activities.Hosting;
|
||
|
using System.Activities.Persistence;
|
||
|
using System.Collections.Generic;
|
||
|
using System.ComponentModel;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using System.Runtime;
|
||
|
using System.Xml.Linq;
|
||
|
|
||
|
public class CompensationExtension : PersistenceParticipant, IWorkflowInstanceExtension
|
||
|
{
|
||
|
static readonly XNamespace compensationNamespace = XNamespace.Get("urn:schemas-microsoft-com:System.Activities/4.0/compensation");
|
||
|
static readonly XName compensationExtensionData = compensationNamespace.GetName("Data");
|
||
|
|
||
|
[Fx.Tag.SynchronizationObject(Blocking = false)]
|
||
|
Dictionary<long, CompensationTokenData> compensationTokenTable;
|
||
|
|
||
|
public CompensationExtension()
|
||
|
{
|
||
|
this.compensationTokenTable = new Dictionary<long, CompensationTokenData>();
|
||
|
}
|
||
|
|
||
|
internal Dictionary<long, CompensationTokenData> CompensationTokenTable
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.compensationTokenTable;
|
||
|
}
|
||
|
private set
|
||
|
{
|
||
|
this.compensationTokenTable = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal long Id
|
||
|
{
|
||
|
get;
|
||
|
set;
|
||
|
}
|
||
|
|
||
|
internal Bookmark WorkflowCompensation
|
||
|
{
|
||
|
get;
|
||
|
set;
|
||
|
}
|
||
|
|
||
|
internal Bookmark WorkflowConfirmation
|
||
|
{
|
||
|
get;
|
||
|
set;
|
||
|
}
|
||
|
|
||
|
internal Bookmark WorkflowCompensationScheduled
|
||
|
{
|
||
|
get;
|
||
|
private set;
|
||
|
}
|
||
|
|
||
|
internal bool IsWorkflowCompensationBehaviorScheduled
|
||
|
{
|
||
|
get;
|
||
|
private set;
|
||
|
}
|
||
|
|
||
|
internal WorkflowInstanceProxy Instance
|
||
|
{
|
||
|
get;
|
||
|
private set;
|
||
|
}
|
||
|
|
||
|
internal void Add(long compensationId, CompensationTokenData compensationToken)
|
||
|
{
|
||
|
Fx.Assert(compensationToken != null, "compensationToken must be valid");
|
||
|
|
||
|
this.CompensationTokenTable[compensationId] = compensationToken;
|
||
|
}
|
||
|
|
||
|
internal void Remove(long compensationId)
|
||
|
{
|
||
|
this.CompensationTokenTable.Remove(compensationId);
|
||
|
}
|
||
|
|
||
|
internal CompensationTokenData Get(long compensationId)
|
||
|
{
|
||
|
CompensationTokenData compensationToken = null;
|
||
|
this.CompensationTokenTable.TryGetValue(compensationId, out compensationToken);
|
||
|
return compensationToken;
|
||
|
}
|
||
|
|
||
|
internal Bookmark FindBookmark(long compensationId, CompensationBookmarkName bookmarkName)
|
||
|
{
|
||
|
CompensationTokenData compensationToken = null;
|
||
|
Bookmark bookmark = null;
|
||
|
|
||
|
if (this.CompensationTokenTable.TryGetValue(compensationId, out compensationToken))
|
||
|
{
|
||
|
bookmark = compensationToken.BookmarkTable[bookmarkName];
|
||
|
}
|
||
|
|
||
|
return bookmark;
|
||
|
}
|
||
|
|
||
|
internal void SetupWorkflowCompensationBehavior(NativeActivityContext context, BookmarkCallback callback, Activity workflowCompensationBehavior)
|
||
|
{
|
||
|
this.WorkflowCompensationScheduled = context.CreateBookmark(callback);
|
||
|
|
||
|
Fx.Assert(workflowCompensationBehavior != null, "WorkflowCompensationBehavior must be valid");
|
||
|
context.ScheduleSecondaryRoot(workflowCompensationBehavior, null);
|
||
|
|
||
|
// Add the root compensationToken to track all root CA execution order.
|
||
|
this.Add(CompensationToken.RootCompensationId, new CompensationTokenData(CompensationToken.RootCompensationId, CompensationToken.RootCompensationId));
|
||
|
this.IsWorkflowCompensationBehaviorScheduled = true;
|
||
|
}
|
||
|
|
||
|
internal long GetNextId()
|
||
|
{
|
||
|
return ++this.Id;
|
||
|
}
|
||
|
|
||
|
internal void NotifyMessage(NativeActivityContext context, long compensationId, CompensationBookmarkName compensationBookmark)
|
||
|
{
|
||
|
Bookmark bookmark = FindBookmark(compensationId, compensationBookmark);
|
||
|
|
||
|
if (bookmark != null)
|
||
|
{
|
||
|
context.ResumeBookmark(bookmark, compensationId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.BookmarkNotRegistered(compensationBookmark)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes,
|
||
|
Justification = "The inherit class don't need to call this method or access this method")]
|
||
|
IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.InterfaceMethodsShouldBeCallableByChildTypes,
|
||
|
Justification = "The inherit class don't need to call this method or access this method")]
|
||
|
void IWorkflowInstanceExtension.SetInstance(WorkflowInstanceProxy instance)
|
||
|
{
|
||
|
this.Instance = instance;
|
||
|
}
|
||
|
|
||
|
// PersistenceParticipant
|
||
|
protected override void CollectValues(out IDictionary<XName, object> readWriteValues, out IDictionary<XName, object> writeOnlyValues)
|
||
|
{
|
||
|
writeOnlyValues = null;
|
||
|
readWriteValues = new Dictionary<XName, object>(1)
|
||
|
{
|
||
|
{
|
||
|
compensationExtensionData,
|
||
|
new List<object>(6)
|
||
|
{
|
||
|
this.CompensationTokenTable,
|
||
|
this.WorkflowCompensation,
|
||
|
this.WorkflowConfirmation,
|
||
|
this.WorkflowCompensationScheduled,
|
||
|
this.IsWorkflowCompensationBehaviorScheduled,
|
||
|
this.Id
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
protected override void PublishValues(IDictionary<XName, object> readWriteValues)
|
||
|
{
|
||
|
object data;
|
||
|
|
||
|
if (readWriteValues.TryGetValue(compensationExtensionData, out data))
|
||
|
{
|
||
|
List<object> list = (List<object>)data;
|
||
|
this.CompensationTokenTable = (Dictionary<long, CompensationTokenData>)list[0];
|
||
|
this.WorkflowCompensation = (Bookmark)list[1];
|
||
|
this.WorkflowConfirmation = (Bookmark)list[2];
|
||
|
this.WorkflowCompensationScheduled = (Bookmark)list[3];
|
||
|
this.IsWorkflowCompensationBehaviorScheduled = (bool)list[4];
|
||
|
this.Id = (long)list[5];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|