Camada de Infraestrutura
Arquitetura Limpa
Criação do Projeto de Infraestrutura
O projeto de infraestrutura é criado como uma biblioteca de classes independente:
dotnet new classlib -o CleanArchitectureStore.Infrastructure
dotnet sln add .\CleanArchitectureStore.Infrastructure\Este projeto constitui a camada mais externa na Arquitetura Limpa, responsável por implementações concretas de detalhes técnicos como persistência de dados, comunicação externa e integrações com sistemas de terceiros.
Configuração de Dependências
Referência ao Projeto de Domínio
O projeto de infraestrutura referencia o domínio para acessar as interfaces definidas:
dotnet add reference ..\CleanArchitectureStore.Domain\Esta referência estabelece a direção correta de dependência: a infraestrutura depende do domínio, implementando suas abstrações.
Instalação do Entity Framework Core
O pacote necessário para integração com SQL Server é adicionado:
dotnet add package Microsoft.EntityFrameworkCore.SqlServerO arquivo de projeto resultante reflete estas dependências:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CleanArchitectureStore.Domain\CleanArchitectureStore.Domain.csproj" />
</ItemGroup>
</Project>Configuração de Mapeamento de Entidades
Estrutura de Diretórios para Mapeamentos
A organização de mapeamentos é estabelecida no diretório Data/Mappings/, separando claramente a configuração de persistência da lógica de domínio.
Classe de Mapeamento ProductMap
A configuração de mapeamento para a entidade Product é implementada:
Análise da configuração de mapeamento:
ToTable("Product"): Especifica o nome da tabela no banco de dados, permitindo desacoplamento entre o nome da entidade e o nome da tabela.HasKey(x => x.Id): DefineIdcomo chave primária. Em sistemas que utilizamGuid, o Entity Framework Core normalmente configura automaticamente, mas a especificação explícita garante clareza.Configuração da propriedade
Title:.IsRequired(): Impede valoresNULLno banco de dados, garantindo integridade referencial.HasMaxLength(160): Define limite máximo para otimização de armazenamento e prevenção de erros.HasColumnType("NVARCHAR"): Especifica o tipo de dados SQL Server, importante para collation e comparações
Implementação do Contexto de Dados
Classe AppDbContext
O contexto principal de dados é definido como uma especialização de DbContext:
Análise detalhada do AppDbContext:
Construtor Primário: Utiliza a sintaxe de construtor primário do C# 12, recebendo
DbContextOptions<AppDbContext>que contém configurações como connection string.Propriedade DbSet:
public DbSet<Product> Products { get; set; } = null!;A inicialização com
null!(null-forgiving operator) informa ao compilador que a propriedade será inicializada pelo Entity Framework Core, evitando warnings do Nullable Reference Types.O operador
!afirma ao analisador que o valor nunca seránullem tempo de execução.
Método
OnModelCreating:modelBuilder.ApplyConfigurationsFromAssembly(typeof(DependencyInjection).Assembly);Carrega automaticamente todas as classes que implementam
IEntityTypeConfiguration<T>no assembly da infraestrutura.typeof(DependencyInjection).Assemblyobtém a referência ao assembly atual, independentemente de qual classe é utilizada como referência.
Alternativas para Obtenção do Assembly
A escolha de typeof(DependencyInjection).Assembly é arbitrária - qualquer classe definida no projeto de infraestrutura funcionará igualmente.
Implementação do Repositório Concreto
Estrutura de Diretórios para Repositórios
Os repositórios concretos são organizados no diretório Repositories/, separando as implementações das definições de interface no domínio.
Classe ProductRepository
A implementação concreta do repositório é definida:
Características da implementação:
Herança da Interface do Domínio:
IProductRepositoryé definido no projeto de domínio, mantendo o Princípio da Inversão de Dependência.Injeção via Construtor Primário: Recebe
AppDbContextdiretamente no construtor, simplificando a declaração.Implementação Concisa: Utiliza expressão-bodied member para método simples, mantendo legibilidade.
Consulta Eficiente:
FirstOrDefaultAsyncé adequado para buscas por identificador único.Respeito ao CancellationToken: Propaga corretamente o token de cancelamento para operações assíncronas.
Configuração de Injeção de Dependência
Classe DependencyInjection na Infraestrutura
Uma classe estática é criada para encapsular a configuração de serviços de infraestrutura:
Análise da configuração:
Método de Extensão:
AddInfrastructureestendeIServiceCollection, permitindo chamada fluente na configuração da API.Registro de Serviços:
services.AddTransient<IProductRepository, ProductRepository>();Registra
ProductRepositorycomo implementação deIProductRepositoryEscopo
Transient: Nova instância criada a cada solicitação, adequado para serviços stateless
Localização Centralizada: Todos os registros de serviços de infraestrutura são concentrados neste método.
Classe DependencyInjection na Aplicação
Similarmente, a camada de aplicação define sua configuração de dependências:
Configuração do MediatR:
AddMediatR: Método de extensão fornecido pelo pacote MediatR.Extensions.Microsoft.DependencyInjection.Registro por Assembly:
RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly)Escaneia automaticamente o assembly da aplicação para:
Commands/Queries que implementam
IRequest<T>Handlers que implementam
IRequestHandler<TRequest, TResponse>Behaviors (pipeline behaviors)
Pre/Post processors
Configuração Flexível: O parâmetro
configurationpermite personalizações adicionais como:Registro de behaviors de pipeline
Configuração de publicação de notificações
Personalização do lifetime scope dos handlers
Visualização da Estrutura da Solução
A solução completa apresenta a seguinte organização:
Princípios Arquiteturais Aplicados
Dependency Inversion Principle (DIP)
Módulos de Alto Nível (Domínio): Define abstrações (
IProductRepository)Módulos de Baixo Nível (Infraestrutura): Implementa concretizações (
ProductRepository)Direção de Dependência: Infraestrutura → Domínio (correto na Clean Architecture)
Separation of Concerns
Domínio: Regras de negócio e entidades
Aplicação: Orquestração de casos de uso
Infraestrutura: Detalhes técnicos de implementação
Apresentação: Interface com usuário/externo
Testabilidade
Domínio Testável: Sem dependências externas, testável isoladamente
Aplicação Testável: Depende apenas de interfaces, facilmente simulável
Infraestrutura Testável: Pode ser testada com banco de dados em memória
Próximas Etapas para a API
Com a infraestrutura configurada, os preparativos para a camada de apresentação incluem:
Configuração da API
Criação do Projeto API:
dotnet new webapi -o CleanArchitectureStore.ApiAdição à Solução:
dotnet sln add .\CleanArchitectureStore.Api\Referências Necessárias: Projetos Application e Infrastructure
Configuração de Serviços
No Program.cs da API:
Configuração do Banco de Dados
Connection String: Configurada em
appsettings.jsonMigrações: Gerenciadas via CLI do Entity Framework
Health Checks: Monitoramento da conexão com banco
Implementação de Endpoints
Controllers ou endpoints minimal API que:
Recebem requisições HTTP
Mapeiam para Commands/Queries
Invocam MediatR
Transformam Results em respostas HTTP apropriadas
Esta estrutura completa da infraestrutura estabelece uma base sólida para a camada de apresentação, garantindo que todos os detalhes técnicos de persistência e integração estejam adequadamente encapsulados e desacoplados das regras de negócio centrais.
Atualizado