1 #pragma warning disable 1634, 1691 2 3 namespace System.Workflow.ComponentModel 4 { 5 #region Imports 6 7 using System; 8 using System.Collections.Generic; 9 using System.Text; 10 using System.Collections; 11 using System.Runtime.Serialization; 12 using System.Security.Permissions; 13 using System.Diagnostics; 14 using System.Workflow.ComponentModel.Design; 15 16 #endregion 17 18 [Serializable] 19 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] 20 public class QueueEventArgs : EventArgs 21 { 22 IComparable queueName; 23 QueueEventArgs(IComparable queueName)24 internal QueueEventArgs(IComparable queueName) 25 { 26 this.queueName = queueName; 27 } 28 29 public IComparable QueueName 30 { 31 get 32 { 33 return this.queueName; 34 } 35 } 36 } 37 38 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] 39 public sealed class ActivityExecutionContext : IServiceProvider, IDisposable 40 { 41 #region Data members 42 43 // dependency props 44 public static readonly DependencyProperty CurrentExceptionProperty = DependencyProperty.RegisterAttached("CurrentException", typeof(Exception), typeof(ActivityExecutionContext), new PropertyMetadata(null, DependencyPropertyOptions.Default, null, EnforceExceptionSemantics, true)); 45 internal static readonly DependencyProperty GrantedLocksProperty = DependencyProperty.RegisterAttached("GrantedLocks", typeof(Dictionary<string, GrantedLock>), typeof(ActivityExecutionContext)); 46 internal static readonly DependencyProperty CachedGrantedLocksProperty = DependencyProperty.RegisterAttached("CachedGrantedLocks", typeof(Dictionary<string, GrantedLock>), typeof(ActivityExecutionContext), new PropertyMetadata(DependencyPropertyOptions.NonSerialized)); 47 internal static readonly DependencyProperty LockAcquiredCallbackProperty = DependencyProperty.RegisterAttached("LockAcquiredCallback", typeof(ActivityExecutorDelegateInfo<EventArgs>), typeof(ActivityExecutionContext)); 48 49 private Activity currentActivity = null; 50 private ActivityExecutionContextManager contextManager = null; 51 private IStartWorkflow startWorkflowService = null; 52 private bool allowSignalsOnCurrentActivity = false; 53 54 private static Type schedulerServiceType = Type.GetType("System.Workflow.Runtime.Hosting.WorkflowSchedulerService, " + AssemblyRef.RuntimeAssemblyRef); 55 private static Type persistenceServiceType = Type.GetType("System.Workflow.Runtime.Hosting.WorkflowPersistenceService, " + AssemblyRef.RuntimeAssemblyRef); 56 private static Type trackingServiceType = Type.GetType("System.Workflow.Runtime.Tracking.TrackingService, " + AssemblyRef.RuntimeAssemblyRef); 57 private static Type transactionServiceType = Type.GetType("System.Workflow.Runtime.Hosting.WorkflowCommitWorkBatchService, " + AssemblyRef.RuntimeAssemblyRef); 58 private static Type loaderServiceType = Type.GetType("System.Workflow.Runtime.Hosting.WorkflowLoaderService, " + AssemblyRef.RuntimeAssemblyRef); 59 60 #endregion 61 62 #region Members 63 ActivityExecutionContext(Activity activity)64 internal ActivityExecutionContext(Activity activity) 65 { 66 this.currentActivity = activity; 67 } ActivityExecutionContext(Activity activity, bool allowSignalsOnCurrentActivity)68 internal ActivityExecutionContext(Activity activity, bool allowSignalsOnCurrentActivity) 69 : this(activity) 70 { 71 // ExecuteActivity/FaultActivity on root activity will be called by the ScheduleExecutor 72 // we don't want to do child check in that case, so this flag is just to avoid those checks 73 this.allowSignalsOnCurrentActivity = allowSignalsOnCurrentActivity; 74 } 75 76 public Activity Activity 77 { 78 get 79 { 80 if (this.currentActivity == null) 81 #pragma warning suppress 56503 82 throw new ObjectDisposedException("ActivityExecutionContext"); 83 84 return this.currentActivity; 85 } 86 } 87 88 public ActivityExecutionContextManager ExecutionContextManager 89 { 90 get 91 { 92 if (this.currentActivity == null) 93 #pragma warning suppress 56503 94 throw new ObjectDisposedException("ActivityExecutionContext"); 95 96 if (this.contextManager == null) 97 this.contextManager = new ActivityExecutionContextManager(this); 98 99 return this.contextManager; 100 } 101 } 102 103 #endregion 104 105 #region StartWorkflow 106 internal sealed class StartWorkflow : IStartWorkflow 107 { 108 private ActivityExecutionContext executionContext = null; StartWorkflow(ActivityExecutionContext executionContext)109 internal StartWorkflow(ActivityExecutionContext executionContext) 110 { 111 this.executionContext = executionContext; 112 } IStartWorkflow.StartWorkflow(Type workflowType, Dictionary<string, object> namedArgumentValues)113 Guid IStartWorkflow.StartWorkflow(Type workflowType, Dictionary<string, object> namedArgumentValues) 114 { 115 return this.executionContext.WorkflowCoreRuntime.StartWorkflow(workflowType, namedArgumentValues); 116 } 117 } 118 #endregion 119 120 #region IServiceProvider methods 121 GetService()122 public T GetService<T>() 123 { 124 return (T)this.GetService(typeof(T)); 125 } 126 GetService(Type serviceType)127 public Object GetService(Type serviceType) 128 { 129 if (this.currentActivity == null) 130 throw new ObjectDisposedException("ActivityExecutionContext"); 131 132 if (serviceType == typeof(IStartWorkflow)) 133 { 134 if (this.startWorkflowService == null) 135 this.startWorkflowService = new StartWorkflow(this); 136 137 return this.startWorkflowService; 138 } 139 else 140 { 141 if (schedulerServiceType != null && schedulerServiceType.IsAssignableFrom(serviceType)) 142 return null; 143 144 if (persistenceServiceType != null && persistenceServiceType.IsAssignableFrom(serviceType)) 145 return null; 146 147 if (trackingServiceType != null && trackingServiceType.IsAssignableFrom(serviceType)) 148 return null; 149 150 if (transactionServiceType != null && transactionServiceType.IsAssignableFrom(serviceType)) 151 return null; 152 153 if (loaderServiceType != null && loaderServiceType.IsAssignableFrom(serviceType)) 154 return null; 155 } 156 157 return this.currentActivity.WorkflowCoreRuntime.GetService(this.currentActivity, serviceType); 158 } 159 160 #endregion 161 162 #region Context Information 163 164 public Guid ContextGuid 165 { 166 get 167 { 168 if (this.currentActivity == null) 169 #pragma warning suppress 56503 170 throw new ObjectDisposedException("ActivityExecutionContext"); 171 172 return this.currentActivity.ContextActivity.ContextGuid; 173 } 174 } 175 internal int ContextId 176 { 177 get 178 { 179 if (this.currentActivity == null) 180 #pragma warning suppress 56503 181 throw new ObjectDisposedException("ActivityExecutionContext"); 182 183 return this.currentActivity.ContextActivity.ContextId; 184 } 185 } 186 187 #endregion 188 189 #region Activity Execution Signals 190 InitializeActivity(Activity activity)191 internal void InitializeActivity(Activity activity) 192 { 193 if (this.currentActivity == null) 194 throw new ObjectDisposedException("ActivityExecutionContext"); 195 196 if (activity == null) 197 throw new ArgumentNullException("activity"); 198 199 if (!IsValidChild(activity, false)) 200 throw new ArgumentException(SR.GetString(SR.AEC_InvalidActivity), "activity"); 201 202 if (activity.ExecutionStatus != ActivityExecutionStatus.Initialized) 203 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidInitializingState)); 204 205 using (ActivityExecutionContext executionContext = new ActivityExecutionContext(activity)) 206 { 207 using (this.currentActivity.WorkflowCoreRuntime.SetCurrentActivity(activity)) 208 activity.Initialize(executionContext); 209 } 210 } ExecuteActivity(Activity activity)211 public void ExecuteActivity(Activity activity) 212 { 213 if (this.currentActivity == null) 214 throw new ObjectDisposedException("ActivityExecutionContext"); 215 216 if (activity == null) 217 throw new ArgumentNullException("activity"); 218 219 // if this activity is not executing, canceling, faulting OR compensating 220 // then it can not execute a child. 221 if (!this.allowSignalsOnCurrentActivity && 222 ( 223 this.currentActivity.WorkflowCoreRuntime.CurrentActivity.ExecutionStatus == ActivityExecutionStatus.Initialized || 224 this.currentActivity.WorkflowCoreRuntime.CurrentActivity.ExecutionStatus == ActivityExecutionStatus.Closed 225 ) 226 ) 227 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidStateToExecuteChild)); 228 229 if (!IsValidChild(activity, false)) 230 throw new ArgumentException(SR.GetString(SR.AEC_InvalidActivity), "activity"); 231 232 if (activity.ExecutionStatus != ActivityExecutionStatus.Initialized) 233 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidExecutionState)); 234 235 try 236 { 237 activity.SetStatus(ActivityExecutionStatus.Executing, false); 238 } 239 finally 240 { 241 Debug.Assert(activity.ExecutionStatus == ActivityExecutionStatus.Executing); 242 this.currentActivity.WorkflowCoreRuntime.ScheduleItem(new ActivityExecutorOperation(activity, ActivityOperationType.Execute, this.ContextId), IsInAtomicTransaction(activity), false, false); 243 } 244 } CancelActivity(Activity activity)245 public void CancelActivity(Activity activity) 246 { 247 if (this.currentActivity == null) 248 throw new ObjectDisposedException("ActivityExecutionContext"); 249 250 if (activity == null) 251 throw new ArgumentNullException("activity"); 252 253 // if this activity is not executing, canceling, faulting OR compensating 254 // then it can not cancel a child. 255 if (!this.allowSignalsOnCurrentActivity && 256 ( 257 this.currentActivity.WorkflowCoreRuntime.CurrentActivity.ExecutionStatus == ActivityExecutionStatus.Initialized || 258 this.currentActivity.WorkflowCoreRuntime.CurrentActivity.ExecutionStatus == ActivityExecutionStatus.Closed 259 ) 260 ) 261 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidStateToExecuteChild)); 262 263 if (!IsValidChild(activity, false)) 264 throw new ArgumentException(SR.GetString(SR.AEC_InvalidActivity), "activity"); 265 266 if (activity.ExecutionStatus != ActivityExecutionStatus.Executing) 267 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidCancelingState)); 268 269 try 270 { 271 activity.SetStatus(ActivityExecutionStatus.Canceling, false); 272 } 273 finally 274 { 275 this.currentActivity.WorkflowCoreRuntime.ScheduleItem(new ActivityExecutorOperation(activity, ActivityOperationType.Cancel, this.ContextId), IsInAtomicTransaction(activity), false, false); 276 } 277 } CompensateActivity(Activity activity)278 internal void CompensateActivity(Activity activity) 279 { 280 if (this.currentActivity == null) 281 throw new ObjectDisposedException("ActivityExecutionContext"); 282 283 if (activity == null) 284 throw new ArgumentNullException("activity"); 285 286 if (!IsValidNestedChild(activity)) 287 throw new ArgumentException(SR.GetString(SR.AEC_InvalidNestedActivity), "activity"); 288 289 if (activity.ExecutionStatus != ActivityExecutionStatus.Closed) 290 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidCompensatingState)); 291 292 try 293 { 294 activity.SetStatus(ActivityExecutionStatus.Compensating, false); 295 } 296 finally 297 { 298 this.currentActivity.WorkflowCoreRuntime.ScheduleItem(new ActivityExecutorOperation(activity, ActivityOperationType.Compensate, this.ContextId), IsInAtomicTransaction(activity), false, false); 299 } 300 } FaultActivity(Exception e)301 internal void FaultActivity(Exception e) 302 { 303 if (this.currentActivity == null) 304 throw new ObjectDisposedException("ActivityExecutionContext"); 305 306 // the current activity might have closed, in that case, we would like to give the exception to parent 307 if (this.currentActivity.ExecutionStatus == ActivityExecutionStatus.Closed) 308 { 309 if (this.currentActivity.Parent == null) 310 { 311 // this could have happened if the root activity closed, but 312 // then it threw an exception 313 this.currentActivity.WorkflowCoreRuntime.TerminateInstance(e); 314 } 315 else 316 { 317 this.currentActivity.WorkflowCoreRuntime.RaiseException(e, this.currentActivity.Parent, string.Empty); 318 } 319 } 320 else 321 { 322 try 323 { 324 this.currentActivity.SetValueCommon(CurrentExceptionProperty, e, CurrentExceptionProperty.DefaultMetadata, false); 325 this.currentActivity.SetStatus(ActivityExecutionStatus.Faulting, false); 326 } 327 finally 328 { 329 this.currentActivity.WorkflowCoreRuntime.ScheduleItem(new ActivityExecutorOperation(this.currentActivity, ActivityOperationType.HandleFault, this.ContextId, e), IsInAtomicTransaction(this.currentActivity), false, false); 330 } 331 } 332 } 333 CloseActivity()334 public void CloseActivity() 335 { 336 if (this.currentActivity == null) 337 throw new ObjectDisposedException("ActivityExecutionContext"); 338 339 switch (this.currentActivity.ExecutionStatus) 340 { 341 case ActivityExecutionStatus.Executing: 342 this.currentActivity.MarkCompleted(); 343 break; 344 case ActivityExecutionStatus.Canceling: 345 this.currentActivity.MarkCanceled(); 346 break; 347 case ActivityExecutionStatus.Compensating: 348 this.currentActivity.MarkCompensated(); 349 break; 350 case ActivityExecutionStatus.Faulting: 351 this.currentActivity.MarkFaulted(); 352 break; 353 case ActivityExecutionStatus.Closed: 354 break; 355 default: 356 throw new InvalidOperationException(SR.GetString(SR.Error_InvalidClosingState)); 357 } 358 } 359 360 internal void Invoke<T>(EventHandler<T> handler, T e) where T : EventArgs 361 { 362 if (this.currentActivity == null) 363 throw new ObjectDisposedException("ActivityExecutionContext"); 364 365 // let the activity handle it 366 this.currentActivity.Invoke(handler, e); 367 } 368 369 #endregion 370 371 #region Tracking Method 372 373 // user tracking TrackData(object userData)374 public void TrackData(object userData) 375 { 376 if (this.currentActivity == null) 377 throw new ObjectDisposedException("ActivityExecutionContext"); 378 379 if (null == userData) 380 throw new ArgumentNullException("userData"); 381 382 this.currentActivity.WorkflowCoreRuntime.Track(null, userData); 383 } 384 385 // user tracking TrackData(string userDataKey, object userData)386 public void TrackData(string userDataKey, object userData) 387 { 388 if (this.currentActivity == null) 389 throw new ObjectDisposedException("ActivityExecutionContext"); 390 391 if (null == userData) 392 throw new ArgumentNullException("userData"); 393 394 this.currentActivity.WorkflowCoreRuntime.Track(userDataKey, userData); 395 } 396 397 #endregion 398 399 #region Locking methods 400 AcquireLocks(IActivityEventListener<EventArgs> locksAcquiredCallback)401 internal bool AcquireLocks(IActivityEventListener<EventArgs> locksAcquiredCallback) 402 { 403 if (this.currentActivity == null) 404 throw new ObjectDisposedException("ActivityExecutionContext"); 405 406 this.Activity.SetValue(LockAcquiredCallbackProperty, new ActivityExecutorDelegateInfo<EventArgs>(true, locksAcquiredCallback, this.Activity.ContextActivity)); 407 return AcquireLocks(this.Activity); 408 } 409 AcquireLocks(Activity activity)410 private bool AcquireLocks(Activity activity) 411 { 412 // If this activity doesn't have any handles, we have nothing to do. 413 ICollection<string> handles = GetAllSynchronizationHandles(activity); 414 if (handles == null || handles.Count == 0) 415 return true; 416 417 Activity parent = activity.Parent; 418 while (parent != null) 419 { 420 if (parent.SupportsSynchronization || parent.Parent == null) 421 { 422 Dictionary<string, GrantedLock> grantedLocks = (Dictionary<string, GrantedLock>)parent.GetValue(GrantedLocksProperty); 423 if (grantedLocks == null) 424 { 425 grantedLocks = new Dictionary<string, GrantedLock>(); 426 parent.SetValue(GrantedLocksProperty, grantedLocks); 427 } 428 foreach (string handle in handles) 429 { 430 bool acquiredLocks = true; 431 if (!grantedLocks.ContainsKey(handle)) 432 { 433 grantedLocks[handle] = new GrantedLock(activity); 434 } 435 else if (grantedLocks[handle].Holder != activity) 436 { 437 grantedLocks[handle].WaitList.Add(activity); 438 acquiredLocks = false; 439 } 440 if (!acquiredLocks) 441 return false; 442 } 443 } 444 445 // If we reach a parent which has at least one handle, then we do not need to 446 // go any further as the parent would already have acquired all our locks for 447 // itself. Note that we still need to acquire our locks in the same parent if 448 // the parent ProvidesSychronization, hence, this if check is *not* after 449 // "parent = parent.Parent"! 450 ICollection<string> synchronizationHandlesOnParent = (ICollection<string>)parent.GetValue(Activity.SynchronizationHandlesProperty); 451 if (synchronizationHandlesOnParent != null && synchronizationHandlesOnParent.Count != 0) 452 break; 453 454 parent = parent.Parent; 455 } 456 return true; 457 } 458 ReleaseLocks(bool transactional)459 internal void ReleaseLocks(bool transactional) 460 { 461 if (this.currentActivity == null) 462 throw new ObjectDisposedException("ActivityExecutionContext"); 463 464 465 // remove the callback. 466 this.Activity.RemoveProperty(LockAcquiredCallbackProperty); 467 468 // The assumption is that lock contentions will be few. Hence, we optimize serialization 469 // size over performance, for ex. do not persist the list of locks that have already been 470 // granted. 471 ICollection<string> handles = GetAllSynchronizationHandles(this.Activity); 472 if (handles == null || handles.Count == 0) 473 return; 474 475 List<Activity> waitingActivities = new List<Activity>(); 476 Activity parent = Activity.Parent; 477 while (parent != null) 478 { 479 if (parent.SupportsSynchronization || parent.Parent == null) 480 { 481 Dictionary<string, GrantedLock> grantedLocks = (Dictionary<string, GrantedLock>)parent.GetValue(GrantedLocksProperty); 482 483 // if its an transactional release of locks, then release it and then keep it 484 // cached, so that in case of rollback, we can reacuire locks 485 if (transactional) 486 { 487 Dictionary<string, GrantedLock> cachedGrantedLocks = new Dictionary<string, GrantedLock>(); 488 489 if (grantedLocks != null) 490 foreach (KeyValuePair<string, GrantedLock> grantedLockEntry in grantedLocks) 491 cachedGrantedLocks.Add(grantedLockEntry.Key, (GrantedLock)grantedLockEntry.Value.Clone()); 492 493 parent.SetValue(CachedGrantedLocksProperty, cachedGrantedLocks); 494 } 495 496 if (grantedLocks != null) 497 { 498 foreach (string handle in handles) 499 { 500 if (!grantedLocks.ContainsKey(handle)) 501 { 502 continue; 503 } 504 else if (grantedLocks[handle].WaitList.Count == 0) 505 { 506 grantedLocks.Remove(handle); 507 } 508 else if (grantedLocks[handle].Holder != this.Activity) 509 { 510 grantedLocks[handle].WaitList.Remove(this.Activity); 511 } 512 else 513 { 514 // Grant the lock to the next waiting activity. 515 Activity waitingActivity = grantedLocks[handle].WaitList[0]; 516 grantedLocks[handle].WaitList.RemoveAt(0); 517 grantedLocks[handle].Holder = waitingActivity; 518 if (!waitingActivities.Contains(waitingActivity)) 519 waitingActivities.Add(waitingActivity); 520 } 521 } 522 if (grantedLocks.Count == 0) 523 parent.RemoveProperty(GrantedLocksProperty); 524 } 525 } 526 527 // If we reach a parent which has at least one handle, then we do not need to 528 // go any further as the parent would already have acquired all our locks for 529 // itself. Note that we still need to acquire our locks in the same parent if 530 // the parent ProvidesSychronization, hence, this if check is *not* after 531 // "parent = parent.Parent"! 532 ICollection<string> synchronizationHandlesOnParent = (ICollection<string>)parent.GetValue(Activity.SynchronizationHandlesProperty); 533 if (synchronizationHandlesOnParent != null && synchronizationHandlesOnParent.Count != 0) 534 break; 535 536 parent = parent.Parent; 537 } 538 539 // Try and acquire locks for all the waiting activities. 540 foreach (Activity waitingActivity in waitingActivities) 541 { 542 if (AcquireLocks(waitingActivity)) 543 { 544 ActivityExecutorDelegateInfo<EventArgs> waitingActivityCallback = (ActivityExecutorDelegateInfo<EventArgs>)waitingActivity.GetValue(LockAcquiredCallbackProperty); 545 waitingActivityCallback.InvokeDelegate(this.Activity.ContextActivity, EventArgs.Empty, false, transactional); 546 } 547 } 548 } 549 GetAllSynchronizationHandles(Activity activity)550 private ICollection<string> GetAllSynchronizationHandles(Activity activity) 551 { 552 // If the activity doesn't have any handles, do not look at child activities. 553 ICollection<string> handleCollection = (ICollection<string>)activity.GetValue(Activity.SynchronizationHandlesProperty); 554 if (handleCollection == null || handleCollection.Count == 0) 555 return handleCollection; 556 557 List<string> handles = new List<string>(handleCollection); 558 // Collect all child locks and normalize the list. 559 if (activity is CompositeActivity) 560 { 561 Walker walker = new Walker(); 562 walker.FoundActivity += delegate(Walker w, WalkerEventArgs e) 563 { 564 if (e.CurrentActivity == activity) 565 return; 566 567 ICollection<string> handlesOnChild = (ICollection<string>)e.CurrentActivity.GetValue(Activity.SynchronizationHandlesProperty); 568 if (handlesOnChild != null) 569 handles.AddRange(handlesOnChild); 570 }; 571 walker.Walk(activity); 572 } 573 574 // normalize handles 575 handles.Sort(); 576 for (int i = 1; i < handles.Count; i++) 577 { 578 if (handles[i] == handles[i - 1]) 579 handles.RemoveAt(--i); 580 } 581 handles.TrimExcess(); 582 583 // return 584 return handles; 585 } 586 587 #endregion 588 589 #region Instance Operation Methods 590 SuspendWorkflowInstance(string suspendDescription)591 internal void SuspendWorkflowInstance(string suspendDescription) 592 { 593 if (this.currentActivity == null) 594 throw new ObjectDisposedException("ActivityExecutionContext"); 595 596 this.currentActivity.WorkflowCoreRuntime.SuspendInstance(suspendDescription); 597 } TerminateWorkflowInstance(Exception e)598 internal void TerminateWorkflowInstance(Exception e) 599 { 600 if (this.currentActivity == null) 601 throw new ObjectDisposedException("ActivityExecutionContext"); 602 603 if (e == null) 604 throw new ArgumentNullException("e"); 605 606 this.currentActivity.WorkflowCoreRuntime.TerminateInstance(e); 607 } CheckpointInstanceState()608 internal void CheckpointInstanceState() 609 { 610 if (this.currentActivity == null) 611 throw new ObjectDisposedException("ActivityExecutionContext"); 612 613 this.currentActivity.WorkflowCoreRuntime.CheckpointInstanceState(this.currentActivity); 614 } RequestRevertToCheckpointState(EventHandler<EventArgs> handler, EventArgs data, bool suspendOnRevert, string suspendOnRevertInfo)615 internal void RequestRevertToCheckpointState(EventHandler<EventArgs> handler, EventArgs data, bool suspendOnRevert, string suspendOnRevertInfo) 616 { 617 if (this.currentActivity == null) 618 throw new ObjectDisposedException("ActivityExecutionContext"); 619 620 this.currentActivity.WorkflowCoreRuntime.RequestRevertToCheckpointState(this.currentActivity, handler, data, suspendOnRevert, suspendOnRevertInfo); 621 } DisposeCheckpointState()622 internal void DisposeCheckpointState() 623 { 624 if (this.currentActivity == null) 625 throw new ObjectDisposedException("ActivityExecutionContext"); 626 627 this.currentActivity.WorkflowCoreRuntime.DisposeCheckpointState(); 628 } 629 #endregion 630 631 #region Helper Methods 632 IsValidChild(Activity activity, bool allowContextVariance)633 internal bool IsValidChild(Activity activity, bool allowContextVariance) 634 { 635 if (this.currentActivity == null) 636 throw new ObjectDisposedException("ActivityExecutionContext"); 637 638 if (activity == this.currentActivity.WorkflowCoreRuntime.CurrentActivity && this.allowSignalsOnCurrentActivity) 639 return true; 640 641 if (activity.Enabled && activity.Parent == this.currentActivity.WorkflowCoreRuntime.CurrentActivity && (allowContextVariance || activity.Equals(this.Activity.GetActivityByName(activity.QualifiedName, true)))) 642 return true; 643 644 return false; 645 } IsValidNestedChild(Activity activity)646 internal bool IsValidNestedChild(Activity activity) 647 { 648 if (this.currentActivity == null) 649 throw new ObjectDisposedException("ActivityExecutionContext"); 650 651 if (activity == this.currentActivity) 652 return true; 653 654 Activity parentActivity = activity; 655 while (parentActivity != null && parentActivity.Enabled && parentActivity.Parent != this.currentActivity.ContextActivity) 656 parentActivity = parentActivity.Parent; 657 658 return (parentActivity != null && parentActivity.Enabled); 659 } 660 internal IWorkflowCoreRuntime WorkflowCoreRuntime 661 { 662 get 663 { 664 if (this.currentActivity == null) 665 #pragma warning suppress 56503 666 throw new ObjectDisposedException("ActivityExecutionContext"); 667 668 return this.GetService<IWorkflowCoreRuntime>(); 669 } 670 } IsInAtomicTransaction(Activity activity)671 internal static bool IsInAtomicTransaction(Activity activity) 672 { 673 bool isInAtomicTransaction = false; 674 while (activity != null) 675 { 676 if (activity == activity.WorkflowCoreRuntime.CurrentAtomicActivity) 677 { 678 isInAtomicTransaction = true; 679 break; 680 } 681 activity = activity.Parent; 682 } 683 return isInAtomicTransaction; 684 } 685 #endregion 686 687 #region CurrentExceptionProperty Guard EnforceExceptionSemantics(DependencyObject d, object value)688 static void EnforceExceptionSemantics(DependencyObject d, object value) 689 { 690 Activity activity = d as Activity; 691 692 if (activity == null) 693 throw new ArgumentException(SR.GetString(System.Globalization.CultureInfo.CurrentCulture, SR.Error_DOIsNotAnActivity)); 694 695 if (value != null) 696 throw new InvalidOperationException(SR.GetString(System.Globalization.CultureInfo.CurrentCulture, SR.Error_PropertyCanBeOnlyCleared)); 697 698 d.SetValueCommon(CurrentExceptionProperty, null, CurrentExceptionProperty.DefaultMetadata, false); 699 } 700 #endregion 701 702 #region IDisposable Members 703 IDisposable.Dispose()704 void IDisposable.Dispose() 705 { 706 if (this.currentActivity != null) 707 { 708 if (this.contextManager != null) 709 { 710 this.contextManager.Dispose(); 711 this.contextManager = null; 712 } 713 this.currentActivity = null; 714 } 715 } 716 717 #endregion 718 } 719 720 #region Class GrantedLock 721 722 [Serializable] 723 internal class GrantedLock : ICloneable 724 { 725 private Activity holder; 726 private List<Activity> waitList; 727 GrantedLock(Activity holder)728 public GrantedLock(Activity holder) 729 { 730 this.holder = holder; 731 this.waitList = new List<Activity>(); 732 } 733 public Activity Holder 734 { 735 get 736 { 737 return this.holder; 738 } 739 set 740 { 741 this.holder = value; 742 } 743 } 744 public IList<Activity> WaitList 745 { 746 get 747 { 748 return this.waitList; 749 } 750 } 751 752 #region ICloneable Members 753 Clone()754 public object Clone() 755 { 756 GrantedLock clonedGrantedLock = new GrantedLock(this.holder); 757 clonedGrantedLock.waitList.InsertRange(0, this.waitList); 758 return clonedGrantedLock; 759 } 760 #endregion 761 } 762 763 #endregion 764 } 765