Considerar:
public class CtorInjectionExample
{
public CtorInjectionExample(ISomeRepository SomeRepositoryIn, IOtherRepository OtherRepositoryIn)
{
this._someRepository = SomeRepositoryIn;
this._otherRepository = OtherRepositoryIn;
}
public void SomeMethod()
{
//use this._someRepository
}
public void OtherMethod()
{
//use this._otherRepository
}
}
contra:
public class MethodInjectionExample
{
public MethodInjectionExample()
{
}
public void SomeMethod(ISomeRepository SomeRepositoryIn)
{
//use SomeRepositoryIn
}
public void OtherMethod(IOtherRepository OtherRepositoryIn)
{
//use OtherRepositoryIn
}
}
Enquanto a injeção de Ctor dificulta a extensão (qualquer código que chame o ctor precisará ser atualizado quando novas dependências são adicionadas), e a injeção no nível do método parece permanecer mais encapsulada da dependência no nível da classe e não consigo encontrar outros argumentos a favor / contra essas abordagens .
Existe uma abordagem definitiva a ser tomada para injeção?
(NB, procurei informações sobre isso e tentei tornar essa pergunta objetiva.)
Respostas:
Depende, se o objeto injetado for usado por mais de um método na classe e injetar nele em cada método não fizer sentido, você precisará resolver as dependências para cada chamada de método e, mas se a dependência for usada apenas por um método injetado no construtor não é bom, mas como você está alocando recursos que nunca poderiam ser usados.
fonte
Certo, primeiro, vamos lidar com "Qualquer código que chame o ctor precisará ser atualizado quando novas dependências forem adicionadas"; Para ser claro, se você está injetando dependências e tem algum código chamando new () em um objeto com dependências, está fazendo errado .
Seu contêiner de DI deve poder injetar todas as dependências relevantes, para que você não precise se preocupar em alterar a assinatura do construtor, para que o argumento não seja realmente válido.
Quanto à idéia de injeção por método versus por classe, há dois problemas principais com a injeção por método.
Uma questão é que os métodos da sua classe devem compartilhar dependências. É uma maneira de ajudar a garantir que suas classes sejam separadas de maneira eficaz. Se você vir uma classe com um grande número de dependências (provavelmente mais de 4-5), essa classe será a principal candidata. para refatorar em duas classes.
O próximo problema é que, para "injetar" as dependências, por método, você precisará passá-las para a chamada do método. Isso significa que você terá que resolver as dependências antes da chamada do método, portanto, provavelmente terá um monte de código como este:
Agora, digamos que você chamará esse método em 10 locais em torno do seu aplicativo: você terá 10 desses trechos. Em seguida, suponha que você precise adicionar outra dependência ao DoStuff (): você precisará alterar esse trecho 10 vezes (ou agrupá-lo em um método, nesse caso, você está apenas replicando o comportamento do DI manualmente, o que é um desperdício). de tempo).
Portanto, o que você basicamente fez lá fez com que suas classes que utilizavam DI tivessem conhecimento de seu próprio contêiner DI, o que é uma péssima idéia , pois rapidamente leva a um design desajeitado e difícil de manter.
Compare isso à injeção do construtor; Na injeção de construtor, você não está vinculado a um contêiner de DI específico e nunca é diretamente responsável por cumprir as dependências de suas classes; portanto, a manutenção é bastante simples.
Parece-me que você está tentando aplicar a IoC a uma classe que contém vários métodos auxiliares não relacionados, embora seja melhor dividir a classe auxiliar em várias classes de serviço com base no uso e usar o auxiliar para delegar o chamadas. Essa ainda não é uma ótima abordagem (ajudante classificado com métodos que fazem algo mais complexo do que apenas lidar com os argumentos passados para eles geralmente são apenas classes de serviço mal escritas), mas pelo menos manterá seu design um pouco mais limpo .
(NB: Eu já fiz a abordagem que você está sugerindo antes, e foi uma péssima ideia que eu não repeti desde então. Acabei tentando separar classes que realmente não precisavam ser separadas e acabei com um conjunto de interfaces em que cada chamada de método exigia uma seleção quase fixa de outras interfaces. Era um pesadelo para manter.)
fonte
"if you're doing dependency injection and you have any code calling new() on an object with dependencies, you're doing it wrong."
Se você está testando por unidade um método em uma classe, precisa instancia-lo ou usa o DI para instanciar seu código em teste?"any code calling the ctor will need updating"
, meu código de produção não chama os ctors. Por estas razões.Existem vários tipos de inversão de controle , e sua pergunta propõe apenas dois (você também pode usar o factory para injetar dependência).
A resposta é: depende da necessidade. Às vezes é melhor usar um tipo e outro tipo diferente.
Eu pessoalmente gosto de injetores de construtores, pois o construtor existe para inicializar completamente o objeto. Ter que chamar um levantador mais tarde faz com que o objeto não seja totalmente construído.
fonte
Você perdeu a que pelo menos para mim é a injeção de propriedade mais flexível. Eu uso o Castle / Windsor e tudo o que preciso fazer é adicionar uma nova propriedade automática à minha classe e obter o objeto injetado sem problemas e sem interromper nenhuma interface.
fonte