Here is a nice little code I did recently, where the Command Pattern is used with a notification observer like pattern.
First of the Command Pattern, a simple interface for task with an execute method
1 2 3 4 5 6 7 |
public interface ITask { /// <summary> /// Execute the task /// </summary> void Execute(); } |
Then the notification interface, with 2 methods, one when it started and one when its complete and the event delegate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
/// Notification interface /// </summary> public interface INotify { /// <summary> /// Process has start /// </summary> void ProcessStart(); /// <summary> /// Process is Complete /// </summary> void ProcessComplete(); } public class NotifyEventArgs : EventArgs { public enum NotificationStatus { START, COMPLETE, ERROR } ; public NotifyEventArgs(string notficationText, NotificationStatus status) { NotifcationText = notficationText; Status = status; } /// <summary> /// Status of notification /// </summary> public NotificationStatus Status { get; private set; } /// <summary> /// Text to notify /// </summary> public string NotifcationText { get; private set; } } |
Now the class that implements the interface, I used an abstract class so that I can just use a subclass to implement the simple task I wish to have
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
public abstract class AbstractTask : ITask, INotify { /// <summary> /// Event for notification /// </summary> public event EventHandler<NotifyEventArgs> NotificationChanged; /// <summary> /// Task to execute /// </summary> public void Execute() { try { ProcessStart(); ProcessingTask(); ProcessComplete(); } catch (Exception e) { LogException(e); } } /// <summary> /// When task is started call notification /// </summary> public void ProcessStart() { if (NotificationChanged == null) return; NotificationChanged(this, new NotifyEventArgs(NotificationText, NotifyEventArgs.NotificationStatus.START)); } /// <summary> /// When task is complete call notification /// </summary> public void ProcessComplete() { if (NotificationChanged == null) return; NotificationChanged(this, new NotifyEventArgs(NotificationText, NotifyEventArgs.NotificationStatus.COMPLETE)); } /// <summary> /// Log the exception /// </summary> /// <param name="e"></param> protected void LogException(Exception e) { if (NotificationChanged != null) NotificationChanged(this, new NotifyEventArgs(e.ToString(), NotifyEventArgs.NotificationStatus.ERROR)); } /// <summary> /// Text to display for notification /// </summary> protected string NotificationText { get; set; } /// <summary> /// Process task for inheriting class /// </summary> protected abstract void ProcessingTask(); } |
Now I can write a simple class that inherits from AbstractTask like this
1 2 3 4 5 6 7 8 9 10 11 12 |
public class HelloTask: AbstractTask { public HelloTask() { NotificationText = "Hello Task"; } protected override void ProcessingTask() { Console.WriteLine("Hello World"); } } |
Now to consume the task
1 2 3 4 5 6 7 8 9 10 11 |
public static void Main(string[] args) { AbstractTask task = new HelloTask(); task.NotificationChanged += new EventHandler<NotifyEventArgs>(NotifyAction); task.Execute(); } private static void NotifyAction(object source, NotifyEventArgs args) { Console.WriteLine(args.NotificationText); } |
This is more or less the simple form of creating a command pattern to run task that includes a notification to send back. It makes sense to have multiple task like creating users and running database scripts etc etc. This allows one to have flexible design and have an IEnumerable<AbstractTask> and run through each one with an execute method.
Hope this helps 🙂 Happy coding.
Leave A Comment