using MainShell.Common; using MW.WorkFlow; using System; using System.Collections.Generic; using System.Runtime.ExceptionServices; using System.Threading.Tasks; namespace MainShell.Process { public class CompositeActivity : IActivity { private readonly IEnumerable _subSteps; private readonly IEnumerable _finallySteps; public string Name { get; } public CompositeActivity(string name, IEnumerable subSteps) : this(name, subSteps, Array.Empty()) { } public CompositeActivity(string name, IEnumerable subSteps, IEnumerable finallySteps) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Composite activity name cannot be null or whitespace.", nameof(name)); } Name = name; _subSteps = subSteps ?? throw new ArgumentNullException(nameof(subSteps)); _finallySteps = finallySteps ?? Array.Empty(); } public async Task ExecuteAsync(WorkflowContext context, ActivityControl activityControl) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (activityControl == null) { throw new ArgumentNullException(nameof(activityControl)); } activityControl.ThrowIfCancellationRequested(); context.TryGetData(WorkflowContextKeys.ParentActivityName, out var previousParent); context.SetData(WorkflowContextKeys.ParentActivityName, Name); ActivityResult result = ActivityResult.Success; Exception mainException = null; Exception cleanupException = null; try { foreach (IActivity step in _subSteps) { activityControl.ThrowIfCancellationRequested(); result = await step.ExecuteAsync(context, activityControl); if (result != ActivityResult.Success) { break; } } } catch (Exception ex) { mainException = ex; } finally { foreach (IActivity cleanupStep in _finallySteps) { try { ActivityResult cleanupResult = await cleanupStep.ExecuteAsync(context, activityControl); if (mainException == null && result == ActivityResult.Success && cleanupResult != ActivityResult.Success) { result = cleanupResult; } } catch (Exception ex) { if (mainException == null && result == ActivityResult.Success) { cleanupException = ex; break; } } } context.SetData(WorkflowContextKeys.ParentActivityName, previousParent ?? string.Empty); } if (mainException != null) { ExceptionDispatchInfo.Capture(mainException).Throw(); } if (cleanupException != null) { ExceptionDispatchInfo.Capture(cleanupException).Throw(); } return result; } } }