/// <summary> /// Runs pipeline's processors one by one in an order /// they are returned from <see cref="IPipeline.GetProcessors"/>. /// </summary> /// <typeparam name="TArgs"> /// Type of the arguments used in each processors of the pipeline. /// </typeparam> /// <param name="pipeline"> /// The pipeline which processors should be executed. /// </param> /// <param name="args"> /// The arguments that has to be passed to each processor /// of the executed pipeline. /// </param> /// <returns> /// Returns a promise of the pipeline execution. /// </returns> public virtual async Task Run(IPipeline pipeline, Bag bag) { if (pipeline.HasNoValue()) { bag.Debug("Cannot run the pipeline because its value is null."); return; } PipelineInfo pipelineInfo = null; if (OnPipelineStart != null || OnPipelineEnd != null) { pipelineInfo = new PipelineInfo() { Context = bag, Pipeline = pipeline }; } if (OnPipelineStart != null) { OnPipelineStart(this, pipelineInfo); } var processors = pipeline.GetProcessors(); if (bag.Debug) { var pipelineName = pipeline.Name(); var description = pipeline.Description(); if (description.HasValue()) { bag.Debug("Running pipeline [{0}]. Pipeline is {1}".FormatWith(pipelineName, description.ToLower())); } else { bag.Debug("Running pipeline [{0}].".FormatWith(pipelineName)); } await Run(processors, bag).ConfigureAwait(false); bag.Debug("Completed pipeline [{0}].".FormatWith(pipelineName)); } else { await Run(processors, bag).ConfigureAwait(false); } if (OnPipelineEnd != null) { OnPipelineEnd(this, pipelineInfo); } }
public static object Map(this Bag bag, LambdaExpression expression) { if (expression == null) { if (bag.Debug) { bag.Debug("The returned expression was null."); } return(null); } var list = new LinkedList <object>(); foreach (var parameter in expression.Parameters) { var parameterName = parameter.Name; if (bag.Contains(parameterName, out object val)) { if (!parameter.Type.IsAssignableFrom(val.GetType())) { if (bag.Debug) { bag.Debug("The parameter type [{1}] is not assignable from [{2}] for property [{0}] in lambda expression.".FormatWith(parameterName, parameter.Type, val.GetType())); } return(null); } list.AddLast(val); continue; } if (bag.ContainsSingle(parameter.Type, out var valueOfType)) { list.AddLast(valueOfType); continue; } else { if (bag.Debug) { bag.Debug("Bag does not contain a property [{0}].".FormatWith(parameterName)); } return(null); } } var result = expression.Compile().DynamicInvoke(list.ToArray()); return(result); }
/// <summary> /// Additionally to the base class method /// <see cref="SafeTypeProcessor{TArgs}.SafeCondition"/>, /// checks <see cref="PipelineContext.Ended"/> status. /// In case it true, the processor should not be executed. /// </summary> /// <param name="args"> /// Arguments to be processed. /// </param> /// <returns> /// Returns <c>true</c> in case base condition is true and /// <see cref="PipelineContext.Ended"/> property is false, /// otherwise returns <c>false</c> which means that the processor /// should not be executed. /// </returns> public virtual bool SafeCondition(Bag args) { var containProperties = MustHaveProperties(); foreach (var property in containProperties) { if (!args.ContainsKey(property)) { if (args.Debug) { var processorName = this.Name(); args.Debug("The bag misses property [{0}]. Skipping processor [{1}].".FormatWith(property, processorName)); } return(false); } } var missProperties = MustMissProperties(); foreach (var property in missProperties) { if (args.ContainsKey(property)) { if (args.Debug) { var processorName = this.Name(); args.Debug("The bag should not contain property [{0}]. Skipping processor [{1}].".FormatWith(property, processorName)); } return(false); } } if (args.Ended) { args.Debug("The bag contained end property set to True. Skipping processor."); return(false); } return(true); }
/// <summary> /// Runs a collection of the processors. If collection is null or empty no processor will be executed. /// If any processor of the collection is null it will be skipped. /// </summary> /// <typeparam name="TArgs"> /// The type of arguments that has to be passed to each processor /// of the executed collection. /// </typeparam> /// <param name="processors"> /// The collection of the processors to be executed. /// </param> /// <param name="args"> /// The arguments that has to be passed to each processor /// of the executed collection. /// </param> /// <returns> /// Returns a promise of the processors execution. /// </returns> public virtual async Task Run(IEnumerable <IProcessor> processors, Bag bag) { int index = 0; processors = processors ?? Enumerable.Empty <IProcessor>(); foreach (var processor in processors) { if (bag.Debug) { var processorName = processor.Name(); var description = processor.Description(); if (description.HasValue()) { bag.Debug("Running processor at index [{1}]: [{0}]. Processor is {2}".FormatWith(processorName, index, description.ToLower())); } else { bag.Debug("Running processor at index [{1}]: [{0}].".FormatWith(processorName, index)); } await Run(processor, bag).ConfigureAwait(false); if (bag.Ended) { bag.Debug("Completed processor [{0}]. Ending signal has been sent.".FormatWith(processorName)); break; } else { bag.Debug("Completed processor [{0}]. Continue to the next one.".FormatWith(processorName)); } } else { await Run(processor, bag).ConfigureAwait(false); } ++index; } }