# Decorator Pattern In ASP.NET Core

> Let's imagine we have an existing Repository implementation, and we want to introduce caching without changing the original class. The decorator pattern makes this possible, and I'll show you how to implement it with the ASP.NET Core DI container.

Published: 2022-10-08. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/decorator-pattern-in-asp-net-core

The **decorator pattern** lets you add new behavior to an existing class without modifying the original class in any way.
A wrapper class implements the same interface and delegates to the wrapped implementation.
In ASP.NET Core you can wire the decorator up manually in the DI container, or register it with a single `Decorate` call from the Scrutor library.

Let's imagine we have an existing `Repository` implementation, and we want to introduce [**caching**](https://milanjovanovic.tech/blog/caching-in-aspnetcore-improving-application-performance) to reduce the load on the database.

How can we achieve this without changing the original `Repository` implementation?

**Decorator pattern** is a structural design pattern that allows you
to introduce new behavior to an existing class, without modifying the original class in any way.

I'll show you how you can implement this with the **ASP.NET Core DI** container.

## How To Implement The Decorator Pattern

We'll start with an existing `MemberRepository` implementation that implements the `IMemberRepository` interface.

It has only one method, which loads the `Member` from the database.

Here's what the implementation looks like:

```csharp
public interface IMemberRepository
{
    Member GetById(int id);
}

public class MemberRepository : IMemberRepository
{
    private readonly DatabaseContext _dbContext;

    public MemberRepository(DatabaseContext dbContext)
    {
        _dbContext = dbContext;
    }

    public Member GetById(int id)
    {
        return _dbContext
            .Set<Member>()
            .First(member => member.Id == id);
    }
}
```

We want to introduce caching to the `MemberRepository` implementation without modifying the existing class.

To achieve this, we can use the **Decorator pattern** and create a wrapper around our `MemberRepository` implementation.

We can create a `CachingMemberRepository` that will have a dependency on `IMemberRepository`.

```csharp
public class CachingMemberRepository : IMemberRepository
{
    private readonly IMemberRepository _repository;
    private readonly IMemoryCache _cache;

    public CachingMemberRepository(
        IMemberRepository repository,
        IMemoryCache cache)
    {
        _repository = repository;
        _cache = cache;
    }

    public Member GetById(int id)
    {
        string key = $"members-{id}";

        return _cache.GetOrCreate(
            key,
            entry => {
                entry.SetAbsouluteExpiration(
                    TimeSpan.FromMinutes(5));

                return _repository.GetById(id);
            });
    }
}
```

Now I'm going to show you the power of **ASP.NET Core DI**.

We will configure the `IMemberRepository` to resolve an instance of `CachingMemberRepository`,
while it will receive the `MemberRepository` instance as its dependency.

## Configuring The Decorator In ASP .NET Core DI

For the DI container to be able to resolve `IMemberRepository` as `CachingMemberRepository`,
we need to manually configure the service.

We can use the overload that exposes a service provider,
that we will use to resolve the services required to construct a `MemberRepository`.

Here's what the configuration would look like:

```csharp
services.AddScoped<IMemberRepository>(provider => {
    var context = provider.GetService<DatabaseContext>();
    var cache = provider.GetService<IMemoryCache>();

    return new CachingRepository(
         new MemberRepository(context),
         cache);
});
```

Now you can inject the `IMemberRepository`, and the DI will be able to resolve an instance of `CachingMemberRepository`.

## Configuring The Decorator With Scrutor

If the previous approach seems _cumbersome_ to you and like a lot of manual work - that's because it is.

However, there is a simpler way to achieve the same behavior.

We can use the **[Scrutor](https://github.com/khellang/Scrutor)** library to register the decorator:

```csharp
services.AddScoped<IMemberRepository, MemberRepository>();

services.Decorate<IMemberRepository, CachingMemberRepository>();
```

**[Scrutor](https://github.com/khellang/Scrutor)** exposes the `Decorate` method.
The call to `Decorate` will register the `CachingMemberRepository` while ensuring
that it receives the expected `MemberRepository` instance as its dependency.

I think this approach is much simpler, and it's what I use in my projects.

---

## Frequently asked questions

### What is the decorator pattern?

The decorator pattern is a structural design pattern that lets you introduce new behavior to an existing class without modifying the original class in any way. A wrapper class implements the same interface and delegates to the wrapped implementation.

### How do you add caching to a repository without changing it?

Create a decorator such as CachingMemberRepository that implements the same IMemberRepository interface and depends on the inner repository. It uses IMemoryCache with an absolute expiration to return cached results and only calls the real repository on a cache miss.

### How do you register a decorator in the ASP.NET Core DI container?

Use the registration overload that exposes a service provider: resolve the dependencies, construct the inner repository, and return the decorator wrapping it. The container then resolves the interface to the decorator everywhere it is injected.

### What is Scrutor and how does it help with decorators?

Scrutor is a library that adds a Decorate method on top of the built-in DI container. After registering the normal implementation, one Decorate call registers the decorator and ensures it receives the expected inner instance, which is much simpler than manual configuration.
