using System; using System.Collections.Generic; using Core.Common.Base.Properties; using log4net; namespace Core.Common.Base.Service { /// /// Abstract class that can be used for performing activies (like calculations, data imports, data exports, etc.). /// The regular workflow for completely performing an is: -> . /// can be called for cancelling a running . /// public abstract class Activity { public event EventHandler ProgressChanged; private readonly ILog log = LogManager.GetLogger(typeof(Activity)); private string progressText; /// /// Constructs a new . /// protected Activity() { LogMessages = new List(); } /// /// Gets or sets the name of the . /// public virtual string Name { get; set; } /// /// Gets or sets the of the . /// public ActivityStatus Status { get; protected set; } /// /// Gets or sets the progress text of the . /// listeners are notified when the progress text is set. /// public string ProgressText { get { return progressText; } protected set { progressText = value; OnProgressChanged(); } } /// /// Gets or sets the collection of log messages of the (which is appended while performing the ). /// public IList LogMessages { get; private set; } /// /// This method runs the . /// public void Run() { try { OnExecute(); if (Status == ActivityStatus.Failed || Status == ActivityStatus.Cancelled) { // keep this status return; } } catch (Exception e) { Status = ActivityStatus.Failed; log.Error(e.Message); return; } if (Status == ActivityStatus.Failed) { log.ErrorFormat(Resources.Activity_Run_Execution_of_0_has_failed, Name); return; } Status = ActivityStatus.Executed; } /// /// This method cancels a running . /// public void Cancel() { ChangeState(OnCancel, ActivityStatus.Cancelled); } /// /// This method finishes an that successfully ran. /// Successfully ran activities can be identified by a not equal to or . /// public void Finish() { if (Status != ActivityStatus.Failed && Status != ActivityStatus.Cancelled) { ChangeState(OnFinish, ActivityStatus.Finished); } } /// /// Executes one step. This method will be called multiple times to allow for multiple /// execution steps. After calling this method, will be set to /// if no error has occurred. /// /// /// Set to /// when an error has occurred while executing. /// protected abstract void OnExecute(); /// /// Activity has finished successfully. After calling this method, /// will be set to if no error has occurred. /// protected abstract void OnFinish(); /// /// Cancels current run. will change to /// after this method has been called. /// protected abstract void OnCancel(); private void OnProgressChanged() { if (ProgressChanged != null) { ProgressChanged(this, EventArgs.Empty); } } private void ChangeState(Action transitionAction, ActivityStatus statusAfter) { try { transitionAction(); if (Status == ActivityStatus.Failed) { return; } } catch (Exception e) { Status = ActivityStatus.Failed; log.Error(e.Message); return; } Status = statusAfter; } } }