//---------------------------------------------------------------- // 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 compensationTokenTable; public CompensationExtension() { this.compensationTokenTable = new Dictionary(); } internal Dictionary 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 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 readWriteValues, out IDictionary writeOnlyValues) { writeOnlyValues = null; readWriteValues = new Dictionary(1) { { compensationExtensionData, new List(6) { this.CompensationTokenTable, this.WorkflowCompensation, this.WorkflowConfirmation, this.WorkflowCompensationScheduled, this.IsWorkflowCompensationBehaviorScheduled, this.Id } } }; } protected override void PublishValues(IDictionary readWriteValues) { object data; if (readWriteValues.TryGetValue(compensationExtensionData, out data)) { List list = (List)data; this.CompensationTokenTable = (Dictionary)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]; } } } }