Analista em Computação/Ênfase em Programação de Sistemas na Tecnologia Microsoft
À luz das boas práticas de DI e lifetimes no ASP.NET Core, qual conjunto de correções alinha o projeto com dependências explícitas, testáveis e seguras para concorrência?
AManter ProcessingService e EmailSender como Singleton, trocando IOptionsSnapshot por IOptionsSnapshot (inalterado) e guardando um IServiceProvider interno para criar AppDbContext sob demanda; seguir com HttpClient direto e property injection em EmailSender.
BTornar tudo Transient para evitar estado compartilhado; injetar HttpClient estático por desempenho; manter Service Locator no controlador porque "flexibiliza" a resolução.
CUsar injeção por construtor em todas as classes; registrar ProcessingService como Scoped; substituir HttpClient por IHttpClientFactory; usar IOptionsMonitor em singletons IOptionsSnapshot apenas no escopo da requisição; no SyncWorker, criar um escopo por iteração com IServiceScopeFactory e resolver serviços Scoped dentro dele; em cenários de background que e precisam de EF, preferir IDbContextFactory; remover property injection obrigatória e o Service Locator do controlador.
DPromover AppDbContext a Singleton para casar com ProcessingService singleton; substituir IOptionsSnapshot por valores lidos de IConfiguration diretamente; manter HttpClient direto injetar o ProcessingService no SyncWorker sem criação de escopos.
ETrocar ProcessingService para Scoped, mas manter IOptionsSnapshot dentro de EmailSender Singleton; continuar com Service Locator apenas nos controladores e usar HttpClient direto, pois o AddHttpClient já foi chamado.
Revelar gabarito e comentário▾
GabaritoC — Usar injeção por construtor em todas as classes; registrar ProcessingService como Scoped; substituir HttpClient por IHttpClientFactory; usar IOptionsMonitor em singletons IOptionsSnapshot apenas no escopo da requisição; no SyncWorker, criar um escopo por iteração com IServiceScopeFactory e resolver serviços Scoped dentro dele; em cenários de background que e precisam de EF, preferir IDbContextFactory; remover property injection obrigatória e o Service Locator do controlador.
Comentário gerado por IA. É um apoio ao estudo, ancorado em fontes, mas pode conter imprecisões — confira sempre na fonte oficial (lei, súmula, edital e gabarito da banca). Encontrou um erro? Use “Reportar”.
DI e Lifetimes no ASP.NET Core
Gabarito: alternativa C. A correção proposta em C segue rigorosamente as boas práticas de injeção de dependência do ASP.NET Core: uso de injeção por construtor, lifetimes corretos (ProcessingService como Scoped), substituição de HttpClient direto por IHttpClientFactory, utilização de IServiceScopeFactory para criar escopos em serviços de background, preferência por IDbContextFactory para evitar conflitos de escopo com EF Core, remoção de Service Locator e property injection. Tudo isso garante dependências explícitas, testabilidade e segurança para concorrência.
Alternativa A — ❌ Incorreta
Manter ProcessingService e EmailSender como Singleton com IServiceProvider interno para criar AppDbContext sob demanda configura uma dependência cativa (captive dependency): serviços Scoped vivendo dentro de Singleton – o AppDbContext (que deve ser Scoped) torna-se efetivamente Singleton, quebrando o isolamento por requisição e gerando problemas de concorrência. O uso de HttpClient direto sem IHttpClientFactory causa exaustão de sockets e fere as boas práticas. Property injection é considerada um anti-pattern, pois esconde dependências e dificulta testes.
Alternativa B — ❌ Incorreta
Registrar tudo como Transient resolve o estado compartilhado, mas é ineficiente (cria instâncias desnecessárias) e não atende a necessidades de escopo (ex.: DbContext perde rastreamento de mudanças por requisição). HttpClient estático (mesmo que via IHttpClientFactory) é desaconselhado; o correto é gerenciar a vida útil com a factory. Manter Service Locator no controlador viola o princípio da injeção explícita e dificulta a testabilidade.
Alternativa C — ✅ Correta ⟵ GABARITO
Esta alternativa aplica todas as correções recomendadas pela documentação oficial do ASP.NET Core:
Injeção por construtor em todas as classes, tornando dependências explícitas.
ProcessingService como Scoped: coerente com o ciclo de vida da requisição.
IHttpClientFactory para criar e gerenciar HttpClient, evitando problemas de socket.
IOptionsMonitor em singletons para ler configurações dinâmicas; IOptionsSnapshot apenas em escopos de requisição.
IServiceScopeFactory no SyncWorker para criar um escopo por iteração e resolver serviços Scoped internamente, evitando dependências cativas.
IDbContextFactory em cenários de background para obter instâncias isoladas de DbContext, cada uma com seu próprio escopo.
Remoção de property injection e Service Locator.
Tudo isso garante aplicações testáveis, seguras para concorrência e aderentes ao padrão de injeção de dependência.
Alternativa D — ❌ Incorreta
Promover AppDbContext a Singleton é gravíssimo: o DbContext não é thread-safe e o uso simultâneo por várias requisições causaria exceções de concorrência. Substituir IOptionsSnapshot por IConfiguration diretamente perde os benefícios de recarga e escopo. HttpClient direto persiste o problema de gerenciamento de sockets. Injetar ProcessingService (que deve ser Scoped) diretamente em SyncWorker sem criar escopo gera uma dependência cativa, pois o Singleton do worker capturaria a mesma instância por toda a vida do aplicativo.
Alternativa E — ❌ Incorreta
Manter IOptionsSnapshot dentro de EmailSender Singleton é inadequado: IOptionsSnapshot é projetado para ser injetado em serviços Scoped (uma instância por requisição). Ao usá-lo em um Singleton, a instância capturada seria a da primeira requisição ou o valor nunca atualizaria (dependendo da implementação), violando o propósito. Continuar com Service Locator e HttpClient direto mantém os anti-patterns.
NÃO CAIA NESSA!
A banca tenta confundir o candidato com alternativas que misturam lifetimes de forma aparentemente plausível, mas que escondem dependências cativas (ex.: Singleton consumir Scoped) e anti-patterns como Service Locator. A chave é lembrar que serviços Scoped não podem viver dentro de Singletons sem criar escopos explícitos (via IServiceScopeFactory), e que o DbContext é sempre Scoped – nunca Singleton. Memorize: DbContext = Scoped, Background tasks = IServiceScopeFactory, HttpClient = IHttpClientFactory.