DEV Community

Rodrigo Schemes
Rodrigo Schemes

Posted on

2

Decorator Pattern com Scrutor no Asp.Net Core

Introdução

Uma das vantagens do ASP.NET Core é a sua capacidade de usar injeção de dependência para gerenciar serviços e componentes. No entanto, às vezes você pode precisar adicionar funcionalidades adicionais a esses serviços sem modificar seu código. É aí que o Decorator Pattern entra em jogo, e uma ótima maneira de implementá-lo é usando a biblioteca Scrutor.

Decorator Pattern

O Decorator Pattern é um padrão de design estrutural que permite adicionar comportamento adicional a um objeto existente, sem modificar sua estrutura. Isso é feito criando classes decoradoras que envolvem o objeto original e adicionam as funcionalidades desejadas.

Scrutor

O Scrutor é uma biblioteca para facilitar a implementação do Decorator Pattern ao injetar serviços em tempo de execução. Ele fornece uma maneira simples e limpa de adicionar funcionalidades a serviços existentes.

Implementando o Decorator Pattern com Scrutor

Vamos dar uma olhada em como implementar o Decorator Pattern com o Scrutor em um exemplo prático.

Suponha que você tenha um repositório IClienteRepositorio que realiza operações relacionadas a Clientes em sua API. Você deseja adicionar uma camada de cache a esse serviço sem modificar seu código existente.

1. Crie uma Interface do seu Repositório de Clientes: Essa interface é usada para representar um repositório de clientes, onde você pode buscar um cliente por seu ID.

public interface IClienteRepositorio
{
   Task<Cliente?> ObterPorIdAsync(int id);
}
Enter fullscreen mode Exit fullscreen mode

2. Implemente a Interface do Repositório: Esta classe ClienteRepositorio implementa a interface IClienteRepositorio e fornece uma implementação para o método ObterPorIdAsync, que busca um cliente pelo seu ID em um contexto de banco de dados.

   public class ClienteRepositorio : IClienteRepositorio
   {
       private readonly AppDbContexto _appDbContexto;

       public ClienteRepositorio(AppDbContexto appDbContexto)
       {
           _appDbContexto = appDbContexto;
       }

       public async Task<Cliente?> ObterPorIdAsync(int id)
       {
           return await _appDbContexto
               .Set<Cliente>()
               .FirstOrDefaultAsync(cliente => cliente.ClienteId == id);
       }
   }
Enter fullscreen mode Exit fullscreen mode

3. Crie a Classe do Decorator: Essa classe será a implementação do Cache. Ela deverá implementar a interface original do repositório de Clientes. Para simplificar o exemplo, vou utilizar o próprio serviço de Cache em memória do Asp.Net Core, o IMemoryCache

public class ClienteCacheRepositorio : IClienteRepositorio
{
    private readonly IClienteRepositorio _clienteRepositorio;
    private readonly IMemoryCache _memoryCache;

    public ClienteCacheRepositorio(IClienteRepositorio clienteRepositorio, 
        IMemoryCache memoryCache)
    {
        _clienteRepositorio = clienteRepositorio;
        _memoryCache = memoryCache;
    }

    public async Task<Cliente?> ObterPorIdAsync(int id)
    {
        var chave = $"cliente-{id}";

        return await _memoryCache.GetOrCreateAsync(chave, async cacheEntry =>
        {
            cacheEntry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
            return await _clienteRepositorio.ObterPorIdAsync(id);
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Instale o pacote Scrutor: você pode usar o gerenciador de pacotes NuGet com o seguinte comando: dotnet add package Scrutor.

5. Configure a Injeção de Dependência com o Scrutor: No Program.cs, configure a injeção de dependência para usar a classe do Decorator quando o IClienteRepositorio for solicitado.

builder.Services.AddMemoryCache();
builder.Services.AddScoped<IClienteRepositorio, ClienteRepositorio>();
builder.Services.Decorate<IClienteRepositorio, ClienteCacheRepositorio>();
Enter fullscreen mode Exit fullscreen mode

Testando a implementação

Podemos validar o funcionamento do padrão Decorator com o Scrutor através do Debug. Se colocarmos um breakpoint na implementação do método ObterPorIdAsync, ele será executado apenas na primeira vez. Na segunda chamada, será utilizado o Memory Cache.

Podemos verificar o resultado através do tempo de resposta no Postman. Na primeira chamada da API, obtemos o cliente com o código "1". O tempo de resposta foi de 413 ms.

Postman - Primeira Chamada

Na segunda chamada, podemos perceber a diferença no tempo de resposta, que foi de 10 ms, pois ele estava utilizando o cache de memória.

Postman - Segunda Chamada

Conclusão

O Decorator Pattern é uma ferramenta poderosa para adicionar funcionalidades a objetos sem modificar seu código existente. Com o Scrutor em ASP.NET Core, você pode implementar facilmente o padrão Decorator ao injetar serviços em tempo de execução. Isso permite que você mantenha seu código limpo, modular e facilmente extensível.

Em resumo, os benefícios do Decorator Pattern são:

  1. Flexibilidade: Permite adicionar funcionalidades extras a objetos sem modificar seu código original.
  2. Manutenção Simples: Facilita a manutenção e evita classes excessivamente complexas.
  3. Composição Dinâmica: Permite combinar funcionalidades de maneira flexível.
  4. Reutilização de Código: Os decoradores podem ser reutilizados em diferentes partes do sistema.
  5. Segregação de Responsabilidades: Mantém as classes com responsabilidades únicas.
  6. Adere aos Princípios SOLID: Segue princípios de design de software sólidos.
  7. Escalabilidade: Facilita a adição de novas funcionalidades sem alterar o código existente.

Referências

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay