Blog / Design Patterns
The Command Design Pattern in C# and .Net
  • Dec 29, 2020
  • 90
  • 88

The next design pattern in the Behavioral Category is the Command Design Pattern. Let's take a look at this design pattern and see when and how to implement this in C# and .Net.

Note: Code can be downloaded at my Github.


Advertisement
 


1. What is the Command Design Pattern?

The Command Design Pattern is used to turn a request into a stand-alone object which has all information about the request. By doing so, the methods for requests can be parameterized and invoked once in need to use.

The command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

2. When to implement the Command Design Pattern?

You may want to use the Command Design Pattern when:

  • You want to parameterize objects with operations
  • You want to queue operations, schedule the executions or execute them remotely
  • You want to reverse the operation

3. How to implement the Command Design Pattern?

Below are steps to implement the Command Design Pattern in C# and .Net

Step 1: Create a Command Interface

The Command interface declares a method for executing a command

1
2
3
4
public interface ICommand
{
    void Execute();
}

Step 2: Create Command Classes

Some commands can implement simple operations on their own. However, some commands can delegate more complex operations to other objects, called "receivers."

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
class SimpleCommand : ICommand
{
    private string _payload = string.Empty;
 
    public SimpleCommand(string payload)
    {
        this._payload = payload;
    }
 
    public void Execute()
    {
        Console.WriteLine($"SimpleCommand: See, I can do simple things like printing ({this._payload})");
    }
}
 
class ComplexCommand : ICommand
{
    private Receiver _receiver;
 
    // Context data, required for launching the receiver's methods.
    private string _a;
 
    private string _b;
 
    // Complex commands can accept one or several receiver objects along
    // with any context data via the constructor.
    public ComplexCommand(Receiver receiver, string a, string b)
    {
        this._receiver = receiver;
        this._a = a;
        this._b = b;
    }
 
    // Commands can delegate to any methods of a receiver.
    public void Execute()
    {
        Console.WriteLine("ComplexCommand: Complex stuff should be done by a receiver object.");
        this._receiver.DoSomething(this._a);
        this._receiver.DoSomethingElse(this._b);
    }
}

Step 3: Create an Invoker and a Receiver class

The Receiver classes contain some important business logic. They know how to perform all kinds of operations, associated with carrying out a request. In fact, any class may serve as a Receiver.

The Invoker is associated with one or several commands. It sends a request to the command.

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
class Receiver
{
    public void DoSomething(string a)
    {
        Console.WriteLine($"Receiver: Working on ({a}.)");
    }
 
    public void DoSomethingElse(string b)
    {
        Console.WriteLine($"Receiver: Also working on ({b}.)");
    }
}
 
// The Invoker is associated with one or several commands. It sends a
// request to the command.
class Invoker
{
    private ICommand _onStart;
 
    private ICommand _onFinish;
 
    // Initialize commands.
    public void SetOnStart(ICommand command)
    {
        this._onStart = command;
    }
 
    public void SetOnFinish(ICommand command)
    {
        this._onFinish = command;
    }
 
    public void DoSomethingImportant()
    {
        Console.WriteLine("Invoker: Does anybody want something done before I begin?");
        if (this._onStart is ICommand)
        {
            this._onStart.Execute();
        }
 
        Console.WriteLine("Invoker: ...doing something really important...");
 
        Console.WriteLine("Invoker: Does anybody want something done after I finish?");
        if (this._onFinish is ICommand)
        {
            this._onFinish.Execute();
        }
    }
}

Done, you can execute the code on the client to see the result.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Program
{
    static void Main(string[] args)
    {
        // The client code can parameterize an invoker with any commands.
        Invoker invoker = new Invoker();
        invoker.SetOnStart(new SimpleCommand("Say Hi!"));
        Receiver receiver = new Receiver();
        invoker.SetOnFinish(new ComplexCommand(receiver, "Send email", "Save report"));
 
        invoker.DoSomethingImportant();
    }
}

Output:


4. Conclusion

The Command Design Pattern is useful for your applications if you need to control when to invoke the received requests. I hope this tutorial is helpful. Please let me know your thoughts in the comment section below.


Using cherry-pick to select specific commits for your Pull Request.1. Create a new branch based on the target of the Pull Requestgit branch cherry-branch origin/master2. Switch to a new branchgit chec ...

After deployment Angular and API on IIS, it's working fine unless I refresh the page. Once refreshed, the web encountered 404 error. In this article, I will explain how to resolve this.Since Angular i ...

There are some benefits of keeping both UI and API parts in the same place for small projects. In this article, I will explain how I did to deploy Angular Web and ASP .Net Core API in the same folder ...

I got CORS error after publishing my API and Angular app to IIS even though CORS is enabled and the origins of the Angular app is added. Below is how I resolved this issue.Just simple, make sure you s ...

1. The Situation:Error Message: Pulse Secure Application failed to load Java. Please install correct JRE version.Description: This issue happens when I'm using a M1 Mac with a correct version of ...

Accelerated Mobile Pages (AMP) focuses on delivering static content from publishers as quickly as possible and possibly rewards early adopters with a boost in rank. Let's see how to implement it ...

Below is how to decrypt/convert a Hex string value into text using VB.Net:Decrypting Hex string value to string in VB.Net Function HexToString(ByVal hex As String) As String Dim text As New Sy ...

After a month of publishing on Google Play, Jungle Words has made it to the Top Android Games To Try Out In April 2021. Please check it out! GameKeys.netGameKeys is a website which introduces gam ...

Centering HTML elements is an important aspect for anything involving designing with CSS. There are various methods of centering things, however, it also depends on the elements that you are working w ...