The Command Pattern in .NET

The Command Pattern in .NET

The post was originally written on the Productive C# blog in 2012.

The Command Pattern encapsulates a request as an?object, thereby letting you parameterize other objects?with different requests, queue or log requests, and support?undoable operations.

The formal definition of the pattern is quite general and it shows how the pattern is versatile and can be used in many scenarios but the real important thing however is the first sentence, the idea that you can define a command in order to encapsulate a request to do something and use that command as a normal object.

The Command Pattern allows you to encapsulate a method invocation.

The biggest benefit is separating the object making requests from the objects that receive and execute the requests.?

In order to describe the pattern I will implement a very simple transactional installer.

Let’s assume we have the following requirements:

  1. The installer allows you to execute an operation
  2. The installer is?independent?by the specific operation executed
  3. The installer is able to?roll back?an operation in case of errors
  4. The installer is able to execute multiple operations as a transaction that is if something goes wrong all previously executed operations will be rolled back

The Command Pattern is the best way to solve this problem.

Let’s start to define the command abstraction:

No alt text provided for this image

We can easily satisfy the first three requirements defining an installer that accept an instance of the command and calls its methods when requested.

No alt text provided for this image

As you can see, the Installer class is completely?independent?by the specific command that is provided in its constructor. In the same way, the command itself is also completely?independent?by the Installer.

You can define as many commands as you want:

No alt text provided for this image
No alt text provided for this image
No alt text provided for this image

You can easily create a program to execute some operations:

No alt text provided for this image

Super easy isn’t it?

What about supporting transactions?

It is here that the real beauty of the pattern comes?in. Because you treat a?command as a normal object, you can aggregate them. Nobody stops you to define a kind of Meta Command that aggregate lots of commands together and in addition implement the support for transactions.

No alt text provided for this image

Consider that the TransactionInstallerCommand is still a command. This means that you can use the Installer class without any changes to run a set of commands in a transactional way.

Let’s see an example of usage.

No alt text provided for this image

Is it not amazing?

In order to simulate an error I created a special command that throws an exception all the time is called.

No alt text provided for this image

This is the output of the program:

No alt text provided for this image

This example and the Command Pattern is a?demonstration?of many Object Oriented Principles

Encapsulate what varies

The implementation and the number of each operation is what varies and we encapsulated this creating the CommandInstaller abstraction.

Favor composition over inheritance

The Installer use a Command using composition. The same does the transaction command that compose many commands together in order to create an extremely flexible command.

Program to interfaces not implementations

Depend on abstractions. Don’t depend on concrete classes

Strive for loosely coupled designs between objects that interact

InstallerCommand is the main interface introduced here that allows a very loosely coupled design with the Installer.

Classes should be open for extension but closed for modifications

It is very easy to create a new command and you don’t need to change the TransactionInstallerCommand in order to use it. TransactionInstallerCommand satisfy the Open/Closed principle.

We didn’t finish yet because I am sure you have a question.

In .NET we have delegates and lambda as a way to represent code as an object. At the end of the day, this is what the command pattern is about or not?

This is absolutely true!

.NET developers are now quite familiar with code like this:

No alt text provided for this image

If you think carefully the Where method is accepting a command as an input and it is independent by the specific command provided. In this case the command is a predicate that is a function that takes an argument and returns a boolean as the result.

No alt text provided for this image

In addition, the predicate requested is just a specific instance of the generic delegate called Func defined as follow:

No alt text provided for this image

This Func object is actually the declaration of a generic command.

How would you implement a method similar to Where without having delegates?

Using the Command Pattern of course!

Let’s try to do this.

No alt text provided for this image
No alt text provided for this image

This is an example of usage:

No alt text provided for this image

What is wrong about this?

Nothing! However you can easily agree with me that the solution using lambda has a big advantage: you don’t need to create a new class all the times you need a new command.

LINQ has been introduced in the language starting from the version 3.0 of C# and is the biggest implementation in the entire framework of the command pattern using lambdas.

LINQ together with some new features made the C# a better language enabling?some of the most useful features available in so called functional languages.


Stefano Merotta

Azure Cloud & Microsoft Technical Architect

1 年

Good article showing a common useful pattern, even without latest language improvements. The only thing that I would change is the example in this post: creating a list for this ienumerable extension method could not be a good suggestion ??

?? Pascal LIBAUD

?? Architecte technique senior chez VISEO

1 年

PredicateCommand<TSource, bool> instead of PredicateCommand<string, bool>. ??

要查看或添加评论,请登录

Andrea Angella的更多文章

  • 15 reasons why you should learn C# in 2024

    15 reasons why you should learn C# in 2024

    Why you should learn C#? This is the question I want to answer in this article. I am Andrea, a Microsoft MVP, Technical…

    8 条评论
  • The importance of defining performance goals

    The importance of defining performance goals

    This post was originally created in the Productive C# blog in 2016. Let’s start from some questions: Is you application…

  • The Singleton Pattern in .NET – Avoid it if you can!

    The Singleton Pattern in .NET – Avoid it if you can!

    This post was originally created in the Productive C# blog in 2012. The Singleton Pattern ensures a class has only one…

    3 条评论
  • Factory Method Pattern in .NET

    Factory Method Pattern in .NET

    This post was originally written on the Productive C# blog in 2012. There is a little bit of confusion around this…

  • The Adapter Pattern in .NET

    The Adapter Pattern in .NET

    This post was originally written in the Productive C# blog in 2012. The Adapter Pattern converts the interface of a…

    2 条评论
  • The Facade Pattern in .NET

    The Facade Pattern in .NET

    This post was originally written on the Productiove C# blog in 2012. The Facade Pattern provides a unified interface to…

  • The Template Method Pattern in .NET

    The Template Method Pattern in .NET

    This post was originally written in the Productive C# blog in 2013. The Template Method Pattern defines the skeleton of…

    1 条评论
  • The Iterator Pattern in .NET

    The Iterator Pattern in .NET

    This post was originally written in the Productive C# blog in 2013. The Iterator Pattern provides a way to access the…

    1 条评论
  • Value Types and Reference Types in C#

    Value Types and Reference Types in C#

    This post was originally published on the Productive C# blog in 2019. Learn about the difference between value types…

  • Agile Estimation

    Agile Estimation

    This post was originally written on the Productive C# blog in 2020. I'd like to share with you some of my notes after…

    1 条评论

社区洞察

其他会员也浏览了