Definições
Inversão de controle é um paradigma de design com o objetivo de reduzir o reconhecimento de implementações concretas do código da estrutura de aplicativo e dar mais controle aos componentes específicos do domínio de sua aplicação. Em um sistema projetado de cima para baixo tradicional, o fluxo lógico do conhecimento da aplicação e da dependência flui dos componentes superiores, os projetados primeiro, para os que foram projetados por último. Como tal, a inversão de controle é uma inversão quase literal da conscientização de controle e dependência em um aplicativo.
Injeção de dependência é um padrão usado para criar instâncias de classes nas quais outras classes confiam sem saber em tempo de compilação qual implementação será usada para fornecer essa funcionalidade.
Trabalhando juntos
A inversão de controle pode utilizar a injeção de dependência, pois é necessário um mecanismo para criar os componentes que fornecem a funcionalidade específica. Outras opções existem e são usadas, por ex. ativadores, métodos de fábrica, etc., mas as estruturas não precisam fazer referência a essas classes de utilitário quando as classes de estrutura podem aceitar a (s) dependência (s) de que precisam.
Exemplos
Um exemplo desses conceitos no trabalho é a estrutura de plug-ins no Refletor . Os plug-ins têm um grande controle do sistema, embora o aplicativo não saiba nada sobre os plug-ins em tempo de compilação. Um único método é chamado em cada um desses plug-ins, Initialize if memory serve, que passa o controle para o plug-in. O framework não sabe o que eles farão, apenas permite que eles façam isso. O controle foi retirado da aplicação principal e dado ao componente que faz o trabalho específico; inversão de controle.
A estrutura de aplicativos permite o acesso à sua funcionalidade por meio de diversos provedores de serviços. Um plug-in recebe referências aos provedores de serviços quando é criado. Essas dependências permitem que o plug-in adicione seus próprios itens de menu, altere a forma como os arquivos são exibidos, exiba suas próprias informações nos painéis apropriados, etc. Como as dependências são transmitidas por interface, as implementações podem mudar e as alterações não quebram o código, desde que o contrato permaneça intacto.
Na época, um método de fábrica era usado para criar os plug-ins usando informações de configuração, reflexão e o objeto Activator (no .NET, pelo menos). Hoje, existem ferramentas, MEF para uma, que permitem um intervalo maior de opções ao injetar dependências, incluindo a capacidade de uma estrutura de aplicativos aceitar uma lista de plug-ins como uma dependência.
Resumo
Embora esses conceitos possam ser usados e forneçam benefícios independentemente, juntos permitem que códigos muito mais flexíveis, reutilizáveis e testáveis sejam gravados. Como tal, eles são conceitos importantes no projeto de soluções orientadas a objetos.