Using Decorators to handle cross-cutting concerns — Part 2 : a practical example
In my previous article I discussed a bit about how to use the Decorator pattern to implement cross-cutting concerns and reduce clutter in your codebase.
Today it’s going to be a bit more practical: we’ll be looking at a small demo I published on Github that makes use of Decorators as well as some other interesting things like .NET Attributes, CQRS and Dependency Injection.
I’m not going to deep dive into the details of CQRS as it would obviously take too much time and it’s outside the scope of this article. I’m using it here because query/command handlers usually expose just one method so there is no need to implement a big interface. Also, I like the pattern a lot :)
So let’s go straight to the code! The repository is available here: https://github.com/mizrael/cross-cutting-concern-attributes
It’s a very small .NET Core WebAPI application, nothing particularly fancy. No infrastructure of course, there’s no need for this article.
There’s just one API controller, exposing a single GET endpoint to retrieve a list of “values”. I might have called it “stuff” instead of “values”, it’s just an excuse to retrieve some data from the backend.
As you may have noticed, there’s no direct reference to the query handler in the API controller: I prefer to use MediatR to avoid injecting too many things in the constructor. It has become an habit so I’m doing it even when there’s just one dependency.
For those who don’t know it, MediatR acts as a simple in-process message bus, allowing quick dispatch of commands, queries and events. So, basically, it’s a very handy tool when implementing CQRS.
The ValuesArchiveHandler class handles the actual execution of the query. Actually it’s not doing much, apart from returning a fixed list of strings.
What we’re interested into actually is that small attribute, [Instrumentation] . It is just a marker, the real grunt-work will be elsewhere. I could have used an interface as well of course, but there are several reasons why I didn’t.
First of all, I prefer to avoid empty interfaces: an interface is a contract, and an interface without method doesn’t define any contract.
Moreover, attributes can always be configured to not propagate to descendant types automatically, something you cannot do with interfaces.
Now, take a look at the InstrumentationQueryHandlerDecorator class. It’s a query handler Decorator, so it gets an instance of a query handler injected in the constructor, and uses it in the Handle() method.
This decorator is not doing anything particular fancy, it’s just using Stopwatch to track how much time the inner handler is taking to complete.
What we’re interested into is the constructor: there the system is checking if the inner instance has been marked with the [Instrumentation] attribute, flipping a boolean value based on the result. That bool will then be used in the Handle() method to turn the instrumentation on or off. That’s it!
I’m using StructureMap as my IoC container and I’m taking care of the handler registration here . In the same file I also decorate all the query handlers with the InstrumentationQueryHandlerDecorator .
Keep in mind that I could have added some smarts here and check at registration time if a particular handler had been decorated with the [Instrumentation] attribute.
That would probably be a better solution as it would avoid runtime type checks, handling everything during the application bootstrap.
I’ll probably add this to the repository, I left it out to keep things simple :)