1 namespace System.Workflow.Activities 2 { 3 #region Imports 4 5 using System; 6 using System.Diagnostics; 7 using System.CodeDom; 8 using System.Drawing; 9 using System.Collections; 10 using System.ComponentModel; 11 using System.ComponentModel.Design; 12 using System.Workflow.ComponentModel; 13 using System.Workflow.ComponentModel.Design; 14 using System.Collections.Generic; 15 using System.Workflow.ComponentModel.Compiler; 16 using System.Workflow.Runtime; 17 using System.Workflow.Activities.Common; 18 19 #endregion 20 21 [ToolboxItem(false)] 22 [Designer(typeof(EventHandlersDesigner), typeof(IDesigner))] 23 [ToolboxBitmap(typeof(EventHandlersActivity), "Resources.events.png")] 24 [ActivityValidator(typeof(EventHandlersValidator))] 25 [SRCategory(SR.Standard)] 26 [AlternateFlowActivityAttribute] 27 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] 28 public sealed class EventHandlersActivity : CompositeActivity, IActivityEventListener<ActivityExecutionStatusChangedEventArgs> 29 { EventHandlersActivity()30 public EventHandlersActivity() 31 { 32 } 33 EventHandlersActivity(string name)34 public EventHandlersActivity(string name) 35 : base(name) 36 { 37 } 38 39 #region Runtime State Specific Dependency Property 40 static DependencyProperty ActivityStateProperty = DependencyProperty.Register("ActivityState", typeof(List<EventHandlerEventActivitySubscriber>), typeof(EventHandlersActivity)); 41 static DependencyProperty IsScopeCompletedProperty = DependencyProperty.Register("IsScopeCompleted", typeof(bool), typeof(EventHandlersActivity), new PropertyMetadata(false)); 42 43 private List<EventHandlerEventActivitySubscriber> ActivityState 44 { 45 get 46 { 47 return (List<EventHandlerEventActivitySubscriber>)base.GetValue(ActivityStateProperty); 48 } 49 set 50 { 51 if (value == null) 52 base.RemoveProperty(ActivityStateProperty); 53 else 54 base.SetValue(ActivityStateProperty, value); 55 } 56 } 57 58 private bool IsScopeCompleted 59 { 60 get 61 { 62 return (bool)base.GetValue(IsScopeCompletedProperty); 63 } 64 set 65 { 66 base.SetValue(IsScopeCompletedProperty, value); 67 } 68 } 69 #endregion 70 UnsubscribeAndClose()71 internal void UnsubscribeAndClose() 72 { 73 base.Invoke<EventArgs>(this.OnUnsubscribeAndClose, EventArgs.Empty); 74 } 75 76 #region Protected Methods OnClosed(IServiceProvider provider)77 protected override void OnClosed(IServiceProvider provider) 78 { 79 base.RemoveProperty(EventHandlersActivity.ActivityStateProperty); 80 base.RemoveProperty(EventHandlersActivity.IsScopeCompletedProperty); 81 } 82 Initialize(IServiceProvider provider)83 protected override void Initialize(IServiceProvider provider) 84 { 85 if (this.Parent == null) 86 throw new InvalidOperationException(SR.GetString(SR.Error_MustHaveParent)); 87 88 base.Initialize(provider); 89 } 90 Execute(ActivityExecutionContext executionContext)91 protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) 92 { 93 if (executionContext == null) 94 throw new ArgumentNullException("executionContext"); 95 96 List<EventHandlerEventActivitySubscriber> eventActivitySubscribers = new List<EventHandlerEventActivitySubscriber>(); 97 this.ActivityState = eventActivitySubscribers; 98 99 for (int i = 0; i < this.EnabledActivities.Count; ++i) 100 { 101 EventDrivenActivity childActivity = this.EnabledActivities[i] as EventDrivenActivity; 102 EventHandlerEventActivitySubscriber eventDrivenSubscriber = new EventHandlerEventActivitySubscriber(childActivity); 103 eventActivitySubscribers.Add(eventDrivenSubscriber); 104 childActivity.EventActivity.Subscribe(executionContext, eventDrivenSubscriber); 105 } 106 return ActivityExecutionStatus.Executing; 107 } Cancel(ActivityExecutionContext executionContext)108 protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext) 109 { 110 if (executionContext == null) 111 throw new ArgumentNullException("executionContext"); 112 113 if (this.ActivityState == null) 114 return ActivityExecutionStatus.Closed; 115 116 bool scopeCompleted = this.IsScopeCompleted; 117 bool canCloseNow = true; 118 119 for (int i = 0; i < this.EnabledActivities.Count; ++i) 120 { 121 EventDrivenActivity childActivity = this.EnabledActivities[i] as EventDrivenActivity; 122 EventHandlerEventActivitySubscriber eventActivitySubscriber = this.ActivityState[i] as EventHandlerEventActivitySubscriber; 123 124 eventActivitySubscriber.PendingExecutionCount = 0; 125 126 ActivityExecutionContextManager contextManager = executionContext.ExecutionContextManager; 127 ActivityExecutionContext childContext = contextManager.GetExecutionContext(childActivity); 128 129 if (childContext != null) 130 { 131 switch (childContext.Activity.ExecutionStatus) 132 { 133 case ActivityExecutionStatus.Canceling: 134 case ActivityExecutionStatus.Faulting: 135 canCloseNow = false; 136 break; 137 case ActivityExecutionStatus.Executing: 138 childContext.CancelActivity(childContext.Activity); 139 canCloseNow = false; 140 break; 141 } 142 } 143 144 if (!scopeCompleted) //UnSubscribe from event. 145 { 146 childActivity.EventActivity.Unsubscribe(executionContext, eventActivitySubscriber); 147 } 148 } 149 150 if (canCloseNow) 151 { 152 this.ActivityState = null; 153 return ActivityExecutionStatus.Closed; 154 } 155 else 156 { 157 return this.ExecutionStatus; 158 } 159 } OnActivityChangeAdd(ActivityExecutionContext executionContext, Activity addedActivity)160 protected override void OnActivityChangeAdd(ActivityExecutionContext executionContext, Activity addedActivity) 161 { 162 if (executionContext == null) 163 throw new ArgumentNullException("executionContext"); 164 165 if (addedActivity == null) 166 throw new ArgumentNullException("addedActivity"); 167 168 EventDrivenActivity eda = addedActivity as EventDrivenActivity; 169 170 EventHandlersActivity activity = (EventHandlersActivity)executionContext.Activity as EventHandlersActivity; 171 EventHandlerEventActivitySubscriber eventActivitySubscriber = new EventHandlerEventActivitySubscriber(eda); 172 173 if (activity.ExecutionStatus == ActivityExecutionStatus.Executing && activity.ActivityState != null && !activity.IsScopeCompleted) 174 { 175 eda.EventActivity.Subscribe(executionContext, eventActivitySubscriber); 176 activity.ActivityState.Insert(activity.EnabledActivities.IndexOf(addedActivity), eventActivitySubscriber); 177 } 178 } OnActivityChangeRemove(ActivityExecutionContext executionContext, Activity removedActivity)179 protected override void OnActivityChangeRemove(ActivityExecutionContext executionContext, Activity removedActivity) 180 { 181 if (executionContext == null) 182 throw new ArgumentNullException("executionContext"); 183 if (removedActivity == null) 184 throw new ArgumentNullException("removedActivity"); 185 186 EventDrivenActivity eda = removedActivity as EventDrivenActivity; 187 188 // find out the status of the scope 189 EventHandlersActivity activity = (EventHandlersActivity)executionContext.Activity as EventHandlersActivity; 190 191 if (activity.ExecutionStatus == ActivityExecutionStatus.Executing && activity.ActivityState != null && !activity.IsScopeCompleted) 192 { 193 for (int i = 0; i < activity.ActivityState.Count; ++i) 194 { 195 EventHandlerEventActivitySubscriber eventSubscriber = activity.ActivityState[i]; 196 if (eventSubscriber.eventDrivenActivity.QualifiedName.Equals(removedActivity.QualifiedName)) 197 { 198 eda.EventActivity.Unsubscribe(executionContext, eventSubscriber); 199 activity.ActivityState.RemoveAt(i); 200 return; 201 } 202 } 203 } 204 } 205 OnWorkflowChangesCompleted(ActivityExecutionContext executionContext)206 protected override void OnWorkflowChangesCompleted(ActivityExecutionContext executionContext) 207 { 208 if (executionContext == null) 209 throw new ArgumentNullException("executionContext"); 210 211 base.OnWorkflowChangesCompleted(executionContext); 212 213 if (this.ActivityState != null) 214 { 215 switch (this.ExecutionStatus) 216 { 217 case ActivityExecutionStatus.Executing: 218 if (this.IsScopeCompleted && AllHandlersAreQuiet(this, executionContext)) 219 executionContext.CloseActivity(); 220 break; 221 case ActivityExecutionStatus.Faulting: 222 case ActivityExecutionStatus.Canceling: 223 if (AllHandlersAreQuiet(this, executionContext)) 224 executionContext.CloseActivity(); 225 break; 226 default: 227 break; 228 } 229 } 230 } 231 #endregion 232 233 #region Private Impls 234 235 #region IActivityEventListener<ActivityExecutionStatusChangedEventArgs> Members 236 OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e)237 void IActivityEventListener<ActivityExecutionStatusChangedEventArgs>.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e) 238 { 239 if (sender == null) 240 throw new ArgumentNullException("sender"); 241 if (e == null) 242 throw new ArgumentNullException("e"); 243 244 ActivityExecutionContext context = sender as ActivityExecutionContext; 245 if (context == null) 246 throw new ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender"); 247 248 EventDrivenActivity eda = e.Activity as EventDrivenActivity; 249 EventHandlersActivity eventHandlers = context.Activity as EventHandlersActivity; 250 251 e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this); 252 253 ActivityExecutionContextManager contextManager = context.ExecutionContextManager; 254 contextManager.CompleteExecutionContext(contextManager.GetExecutionContext(eda)); 255 256 switch (eventHandlers.ExecutionStatus) 257 { 258 case ActivityExecutionStatus.Executing: 259 for (int i = 0; i < eventHandlers.EnabledActivities.Count; ++i) 260 { 261 if (eventHandlers.EnabledActivities[i].QualifiedName.Equals(eda.QualifiedName)) 262 { 263 EventHandlerEventActivitySubscriber eventActivitySubscriber = eventHandlers.ActivityState[i]; 264 265 if (eventActivitySubscriber.PendingExecutionCount > 0) 266 { 267 eventActivitySubscriber.PendingExecutionCount--; 268 eventActivitySubscriber.IsBlocked = false; 269 270 ActivityExecutionContext childContext = contextManager.CreateExecutionContext(eventHandlers.EnabledActivities[i]); 271 childContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, this); 272 childContext.ExecuteActivity(childContext.Activity); 273 } 274 else 275 { 276 eventActivitySubscriber.IsBlocked = true; 277 if (eventHandlers.IsScopeCompleted && AllHandlersAreQuiet(eventHandlers, context)) 278 context.CloseActivity(); 279 } 280 break; 281 } 282 } 283 break; 284 285 case ActivityExecutionStatus.Canceling: 286 case ActivityExecutionStatus.Faulting: 287 if (AllHandlersAreQuiet(eventHandlers, context)) 288 context.CloseActivity(); 289 break; 290 } 291 } 292 293 #endregion 294 295 #region Helpers AllHandlersAreQuiet(EventHandlersActivity handlers, ActivityExecutionContext context)296 private bool AllHandlersAreQuiet(EventHandlersActivity handlers, ActivityExecutionContext context) 297 { 298 ActivityExecutionContextManager contextManager = context.ExecutionContextManager; 299 300 for (int i = 0; i < handlers.EnabledActivities.Count; ++i) 301 { 302 EventDrivenActivity eventDriven = handlers.EnabledActivities[i] as EventDrivenActivity; 303 if (contextManager.GetExecutionContext(eventDriven) != null || (handlers.ActivityState != null && handlers.ActivityState[i].PendingExecutionCount > 0)) 304 return false; 305 } 306 return true; 307 } OnUnsubscribeAndClose(object sender, EventArgs args)308 private void OnUnsubscribeAndClose(object sender, EventArgs args) 309 { 310 if (sender == null) 311 throw new ArgumentNullException("sender"); 312 if (args == null) 313 throw new ArgumentNullException("args"); 314 315 ActivityExecutionContext context = (ActivityExecutionContext)sender; 316 if (context == null) 317 throw new ArgumentException("sender"); 318 319 EventHandlersActivity handlers = context.Activity as EventHandlersActivity; 320 if (context.Activity.ExecutionStatus != ActivityExecutionStatus.Executing) 321 return; 322 323 Debug.Assert(!handlers.IsScopeCompleted, "Only notified of scope body completion once"); 324 handlers.IsScopeCompleted = true; 325 326 ActivityExecutionContextManager contextManager = context.ExecutionContextManager; 327 bool readyToClose = true; 328 for (int i = 0; i < handlers.EnabledActivities.Count; ++i) 329 { 330 EventDrivenActivity evtDriven = handlers.EnabledActivities[i] as EventDrivenActivity; 331 EventHandlerEventActivitySubscriber eventSubscriber = handlers.ActivityState[i]; 332 evtDriven.EventActivity.Unsubscribe(context, eventSubscriber); 333 334 if (contextManager.GetExecutionContext(evtDriven) != null || handlers.ActivityState[i].PendingExecutionCount != 0) 335 readyToClose = false; 336 } 337 338 if (readyToClose) 339 { 340 handlers.ActivityState = null; 341 context.CloseActivity(); 342 } 343 } 344 #endregion 345 346 #region EventSubscriber 347 [Serializable] 348 private sealed class EventHandlerEventActivitySubscriber : IActivityEventListener<QueueEventArgs> 349 { 350 bool isBlocked; 351 int numOfMsgs; 352 353 internal EventDrivenActivity eventDrivenActivity; 354 EventHandlerEventActivitySubscriber(EventDrivenActivity eventDriven)355 internal EventHandlerEventActivitySubscriber(EventDrivenActivity eventDriven) 356 { 357 isBlocked = true; 358 numOfMsgs = 0; 359 this.eventDrivenActivity = eventDriven; 360 } 361 362 internal bool IsBlocked 363 { 364 get 365 { 366 return isBlocked; 367 } 368 set 369 { 370 isBlocked = value; 371 } 372 } 373 374 internal int PendingExecutionCount 375 { 376 get 377 { 378 return numOfMsgs; 379 } 380 set 381 { 382 numOfMsgs = value; 383 } 384 } 385 OnEvent(object sender, QueueEventArgs e)386 void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs e) 387 { 388 if (sender == null) 389 throw new ArgumentNullException("sender"); 390 if (e == null) 391 throw new ArgumentNullException("e"); 392 ActivityExecutionContext context = sender as ActivityExecutionContext; 393 394 if (context == null) 395 throw new ArgumentException("sender"); 396 397 EventHandlersActivity handlers = context.Activity as EventHandlersActivity; 398 399 if (handlers.ExecutionStatus != ActivityExecutionStatus.Executing) 400 return; 401 402 if (!handlers.EnabledActivities.Contains(eventDrivenActivity)) 403 return; //Activity is dynamically removed. 404 405 if (IsBlocked) 406 { 407 IsBlocked = false; 408 ActivityExecutionContextManager contextManager = context.ExecutionContextManager; 409 ActivityExecutionContext childContext = contextManager.CreateExecutionContext(eventDrivenActivity); 410 childContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, handlers); 411 childContext.ExecuteActivity(childContext.Activity); 412 } 413 else 414 { 415 PendingExecutionCount++; 416 } 417 } 418 } 419 #endregion 420 #endregion 421 422 [Browsable(false)] 423 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] GetDynamicActivity(Activity childActivity)424 private Activity GetDynamicActivity(Activity childActivity) 425 { 426 if (childActivity == null) 427 throw new ArgumentNullException("childActivity"); 428 429 if (!this.EnabledActivities.Contains(childActivity)) 430 throw new ArgumentException(SR.GetString(SR.Error_EventHandlersChildNotFound), "childActivity"); 431 else 432 { 433 Activity[] dynamicChildActivity = this.GetDynamicActivities(childActivity); 434 435 if (dynamicChildActivity.Length != 0) 436 return dynamicChildActivity[0]; 437 else 438 return null; 439 } 440 } 441 GetDynamicActivity(String childActivityName)442 public Activity GetDynamicActivity(String childActivityName) 443 { 444 if (childActivityName == null) 445 throw new ArgumentNullException("childActivityName"); 446 447 Activity childActivity = null; 448 449 for (int i = 0; i < this.EnabledActivities.Count; ++i) 450 { 451 if (this.EnabledActivities[i].QualifiedName.Equals(childActivityName)) 452 { 453 childActivity = this.EnabledActivities[i]; 454 break; 455 } 456 } 457 458 if (childActivity != null) 459 return GetDynamicActivity(childActivity); 460 461 throw new ArgumentException(SR.GetString(SR.Error_EventHandlersChildNotFound), "childActivityName"); 462 } 463 } 464 465 internal sealed class EventHandlersValidator : CompositeActivityValidator 466 { Validate(ValidationManager manager, object obj)467 public override ValidationErrorCollection Validate(ValidationManager manager, object obj) 468 { 469 ValidationErrorCollection validationErrors = base.Validate(manager, obj); 470 471 EventHandlersActivity eventHandlers = obj as EventHandlersActivity; 472 if (eventHandlers == null) 473 throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(EventHandlersActivity).FullName), "obj"); 474 475 if (eventHandlers.Parent == null) 476 { 477 validationErrors.Add(new ValidationError(SR.GetString(SR.Error_MustHaveParent), ErrorNumbers.Error_EventHandlersDeclParentNotScope)); 478 return validationErrors; 479 } 480 481 // Parent must support event handlers 482 if (!(eventHandlers.Parent is EventHandlingScopeActivity)) 483 validationErrors.Add(new ValidationError(SR.GetString(SR.Error_EventHandlersDeclParentNotScope, eventHandlers.Parent.QualifiedName), ErrorNumbers.Error_EventHandlersDeclParentNotScope)); 484 485 bool bNotAllEventHandler = false; 486 foreach (Activity activity in eventHandlers.EnabledActivities) 487 { 488 if (!(activity is EventDrivenActivity)) 489 bNotAllEventHandler = true; 490 } 491 492 // validate that all child activities are event driven activities. 493 if (bNotAllEventHandler) 494 validationErrors.Add(new ValidationError(SR.GetString(SR.Error_ListenNotAllEventDriven), ErrorNumbers.Error_ListenNotAllEventDriven)); 495 496 return validationErrors; 497 } 498 } 499 } 500