If you are new to the decorator pattern, let me start with a short explanation:
Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.
A common use case for decorators is to implement Aspect Oriented Programming(AOP) which allows you to implement cross-cutting concerns like logging, caching, …
There are multiple ways to implement this pattern, you can manually implement it, use your DI container, use a source generator to write the boilerplate code or use a dynamic proxy that wraps call to the original class.
It’s this last approach I want to focus on in this blog post. You could use the great Castle.DynamicProxy
library but for simpler use cases, there is a built-in alternative through the System.Reflection.DispatchProxy
class.
Let’s have a look at a small code example on how to use this class.
First we need to create a Decorator class that implements DispatchProxy
:
Remark: Be aware that we cannot use constructor injection to inject parameters(like the logger in the example above).
We could now use the DispatchProxy.Create()
method but I typically create a static method that allows me to wrap an existing class instance
Let's create an interface, corresponding class and apply the decorator:
If we now run this code, the result looks like this:
Sweet!
There are some pros and cons when using this approach:
- Pros
- Works with .NET Standard 1.3+ (so it works with both .NET Framework 4.6+ and .NET Core/.NET 5).
- No 3th party libraries needed.
- Proxies by wrapping the target object, so a proxy can be created around an already existing object.
- Cons
- Proxies interfaces, not classes, so proxied types must implement an interface and access to any members not in the interface (like fields) is complicated.
- Uses reflection, so not usable with AOT.
- No support for async methods/functions.