
Recentemente descobri o atributo [FromServices]
, que faz parte do .Net Core desde a primeira versão.
O atributo [FromServices] permite injeção de dependência a nível de método em controladores Asp.Net Core.
Aqui está um exemplo:
public class UserController : Controller
{
private readonly IApplicationSettings _applicationSettings;
public UserController(IApplicationSettings applicationSettings)
{
_applicationSettings = applicationSettings;
}
public IActionResult Get([FromService]IUserRepository userRepository, int userId)
{
//Do magic
}
}
Por que usar injeção de método em vez de injeção de construtor? A explicação comum é quando um método precisa de dependências e não é usado em nenhum outro lugar, então é um candidato para usar o atributo [FromService]
.
Steven do StackOverflow postou uma resposta contra o uso do atributo [FromService]
:
Para mim, o uso deste tipo de injeção de método em ações de controlador é uma má ideia, porque:
– Tal atributo
[FromServices]
pode ser facilmente esquecido, e você só descobrirá quando a ação for invocada (em vez de descobrir na inicialização da aplicação, onde você pode verificar a configuração da aplicação)– A necessidade de se afastar da injeção de construtor por razões de performance é uma indicação clara de que os componentes injetados são muito pesados para criar, enquanto construtores de injeção devem ser simples, e a criação de componentes deve, portanto, ser muito leve.
– A necessidade de se afastar da injeção de construtor para evitar que os construtores se tornem muito grandes é uma indicação de que suas classes têm muitas dependências e estão se tornando muito complexas. Em outras palavras, ter muitas dependências é uma indicação de que a classe viola o Princípio da Responsabilidade Única. O fato de que suas ações de controlador podem ser facilmente divididas em diferentes classes é prova de que tal controlador não é muito coeso e, portanto, uma indicação de violação do SRP.
Então, em vez de esconder o problema raiz com o uso de injeção de método, aconselho o uso de injeção de construtor como único padrão de injeção aqui e torne seus controladores menores. Isso pode significar, no entanto, que seu esquema de roteamento se torna diferente da estrutura de sua classe, mas isso é perfeitamente aceitável e completamente suportado pelo ASP.NET Core.
De uma perspectiva de testabilidade, aliás, não deveria realmente importar se às vezes há uma dependência que não é necessária. Existem padrões de teste eficazes que resolvem este problema.
Concordo com Steven; se você precisa mover suas dependências do seu controlador para o método porque a classe está construindo muitas dependências, então é hora de dividir o controlador. Você quase certamente está violando o SRP.
O único caso de uso que vejo com injeção de método é late-binding quando uma dependência não está pronta na construção do controlador. Caso contrário, é melhor usar injeção de construtor.
Digo isso porque com injeção de construtor a classe sabe na construção se as dependências estão disponíveis. Com injeção de método, este não é o caso, não se sabe se as dependências estão disponíveis até que o método seja chamado.
Autor: Chuck Conway é especialista em engenharia de software e IA Generativa. Conecte-se com ele nas redes sociais: X (@chuckconway) ou visite-o no YouTube.