/// <summary> /// Validates <see cref="ActionPlan"/> /// </summary> /// <param name="plan"><see cref="ActionPlan"/> to validate.</param> public void Validate(ActionPlan plan) { throw new NotImplementedException(); }
/// <summary>Asynchronously executes all actions in the <see cref="ActionPlan"/> that is specified in <paramref name="plan"/>.</summary> /// <param name="plan">The <see cref="ActionPlan"/> to execute.</param> /// <param name="properties">Collection of global properties. Names should match those returned by <see cref="ActionPlan.Properties"/>.</param> /// <param name="token">The cancellation token that can be used for cancelling execution.</param> /// <returns>The <see cref="Task"/>.</returns> public async Task ExecuteAsync(ActionPlan plan, Dictionary<string, object> properties, CancellationToken token) { this.ThrowErrorIfDisposed(); if (properties == null) { throw new ArgumentNullException("properties"); } this.Validate(plan); // Validate global properties values foreach (var property in properties.Where(property => (property.Value == null))) { throw new ArgumentOutOfRangeException("properties", string.Format("Property '{0}' must contain a value.", property.Key)); } // inject values for non-mandatory properties if not specified. foreach (var property in plan.Properties.Where(property => property.Optional && !properties.ContainsKey(property.Name))) { properties.Add(property.Name, property.Value); } var propertyNames = plan.Properties.Select(propertyRow => propertyRow.Name).ToArray(); if (propertyNames.Any(propertyName => !properties.ContainsKey(propertyName))) { const string MessageFormat = "The properties '{0}' are required. Properties that has been provided are '{1}'"; string message = string.Format(MessageFormat, string.Join(", ", propertyNames), string.Join(", ", properties.Keys)); throw new ArgumentOutOfRangeException("properties", message); } int progress = 0; var propertyCache = properties.ToDictionary( globalProperty => GetPropertyMacroName(plan.GetType().Name, globalProperty.Key), globalProperty => globalProperty.Value); IActionExecutionContext context = new ActionExecutionContext(); foreach (var actionDefinition in plan.Actions) { this.ReportProgress(string.Format("Executing '{0}' operation ... ", actionDefinition.Id), progress); string actionName = actionDefinition.Name; IAction action = this.GetActionByName(actionName); // Set input properties SetActionInputPropertyValues(actionDefinition, action, propertyCache); // Execute action try { await action.ExecuteAsync(context); } catch (Exception e) { string message = string.Format("Execution of action '{0}' failed. Details: {1}", actionDefinition.Id, e.Message); throw new InvalidOperationException(message, e); } // Collect output properties to be available for macro expansion GetActionOutputPropertyValues(actionDefinition, action, propertyCache); // Check if validation should be done foreach (var property in actionDefinition.OutputProperties.Where(property => property.Validate)) { var propertyInfo = GetGetPropertyInfo(action.GetType(), property.Name, actionDefinition.Id); var propertyValue = propertyInfo.GetValue(action); var expectedValue = System.Convert.ChangeType(property.ExpectedValue, propertyInfo.PropertyType); if (!propertyValue.Equals(expectedValue)) { string message = property.ValidationMessage; if (message == null) { string.Format("Action {0} fails validation, property {1} expected {2} but returned {3}", actionDefinition.Id, property.Name, property.ExpectedValue, propertyValue); } else { message = ExpandMacros(message, propertyCache).ToString(); } throw new ArgumentOutOfRangeException("OutputProperties", message); } } progress += 100 / plan.Actions.Length; token.ThrowIfCancellationRequested(); } this.ReportProgress("Execution completed", 100); }
public Task ExecuteAsync(ActionPlan plan, Dictionary<string, object> properties, CancellationToken token) { return null; }
/// <summary> /// Validates <see cref="ActionPlan"/> /// </summary> /// <param name="plan"><see cref="ActionPlan"/> to validate.</param> /// <exception cref="ArgumentNullException">Value of the <paramref name="plan"/> argument is null.</exception> public void Validate(ActionPlan plan) { if (plan == null) { throw new ArgumentNullException("plan"); } this.ThrowErrorIfDisposed(); plan.Validate(); foreach (var actionDefinition in plan.Actions) { string actionName = actionDefinition.Name; IAction action = this.GetActionByName(actionName); // Validate input properties foreach (var inPropertyRow in actionDefinition.InputProperties) { GetSetPropertyInfo(action.GetType(), inPropertyRow.Name, actionDefinition.Id); } // Validate output properties foreach (var outPropertyRow in actionDefinition.OutputProperties) { GetGetPropertyInfo(action.GetType(), outPropertyRow.Name, actionDefinition.Id); } } }