Diferentes maneiras de injetar dependências em Controladores ASP.NET MVC?
-
20-08-2019 - |
Pergunta
Na maioria das amostras que tenho visto na web, DI em controladores de MVC é feito assim
public ProductController(IProductRepository Rep)
{
this._rep = Rep;
}
A ControllerFactory personalizado é usado e ele utiliza a estrutura DI de escolha e o repositório é injetado.
Por que o acima considerado melhor do que
public ProuctController()
{
this._rep = ObjectFactory.GetInstance<IProductRepository>();
}
Isto irá obter os mesmos resultados, mas não exige uma fábrica de controlador personalizado.
Tanto quanto o teste está em causa o Test App pode ter um BootStrapper separado. Dessa forma, quando os controladores estão sendo testados eles podem obter os repositórios falsos e quando eles são utilizados para real que irão receber os reais.
Solução
Construtor de injeção (a primeira abordagem) é melhor do que o padrão de localizador de serviço (a segunda abordagem) por várias razões.
dependências Em primeiro lugar, serviço de localizador de peles. Em seu segundo exemplo, olhando para a interface pública por si só, não há nenhuma maneira de saber que os repositórios de necessidade ProductControllers
.
Além do mais, eu tenho que echo OdeToCode . Acho
IProductRepository repository = Mockery.NewMock<IProductRepository>();
IProductController controller = new ProductController(repository);
é mais clara do que
ObjectFactory.SetFactory(IProductRepository, new MockRepositoryFactory())
IProductController controller = new ProductController();
Especialmente se o ObjectFactory é configurado em forma de SetUp
de um suporte de ensaio.
Finalmente, o padrão de localizador de serviço é comprovadamente sub-óptima em pelo menos um caso particular: quando você está escrevendo código que será consumido por pessoas que escrevem aplicações fora do seu controle. aposta I que as pessoas geralmente preferem injeção de construtor (ou um dos outros métodos DI) porque é aplicável para todos os cenários. Por que não usar o método que abrange todos os casos?
(Martin Fowler oferece uma análise muito mais profunda na "Inversão de Controle Containers e o padrão Dependency Injection" , especialmente a seção "Service Locator vs Dependency Injection").
Outras dicas
A principal desvantagem para o segundo construtor é agora seu contêiner IoC tem de ser devidamente configurado para cada teste. Esta configuração pode se tornar um fardo real como a base de código cresce e os cenários de teste tornam-se mais variada. Os testes são geralmente mais fáceis de ler e manter quando você explicitamente passar em um teste duplo.
Outra preocupação é o acoplamento de um grande número de classes para um quadro específico DI / IOC. Existem maneiras para abstrair-lo fora, é claro, mas você ainda tem código cheio durante todo suas classes para recuperar dependências. Uma vez que todos os quadros bons pode descobrir que dependências que você precisa de olhar para o construtor, é um monte de desperdício de esforços e código duplicado.
Quando você usa a segunda abordagem, as desvantagens são:
- métodos setup / contexto de teste enorme e ilegível são necessários
- O recipiente é acoplado ao controlador
- Você precisa escrever muito mais código
Por que você quer usar um recipiente COI qualquer maneira, quando você não quer que a injeção de dependência?