Estou bastante confortável com a injeção de dependência usando o NInject no MVC3. Enquanto trabalhava em um aplicativo MVC3, desenvolvi uma Controller Creation Factory personalizada usando o NInject, para que qualquer controlador criado tenha dependências injetadas nele através desta Controller Factory.
Agora estou começando a desenvolver um aplicativo do Windows, quero usar a Injeção de Dependência em todo o aplicativo. Cada objeto deve ser criado através do NInject, para facilitar o Teste de Unidade. Por favor, me guie para garantir que todos os objetos criados sejam apenas do NInject Factory.
Por exemplo, se em qualquer janela do Button_Click
evento eu escrever:
TestClass testClass = new TestClass()
e TestClass
tem alguma dependência, digamos, ITest
então deve ser resolvido automaticamente. Eu sei que posso usar:
Ikernel kernel = new StandardKenel()
//AddBinding()
TestClass testClass = kenel.get<TestClass>();
Mas acho tedioso fazer isso toda vez que quero criar um objeto. Ele também força o desenvolvedor a criar o objeto de uma maneira específica. Pode ser melhorado?
Posso ter um repositório central para criação de objeto e, em seguida, toda criação de objeto usará esse repositório automaticamente?
fonte
Respostas:
Para aplicativos clientes, geralmente é melhor adaptar um padrão como MVP (ou MVVM) e usar a ligação de dados do formulário ao ViewModel ou Presenter subjacente.
Para os ViewModels, você pode injetar as dependências necessárias usando a Injeção de Construtor padrão.
Na Raiz de composição do seu aplicativo, você pode conectar todo o gráfico de objetos do seu aplicativo. Você não precisa usar um DI Container (como o Ninject) para isso, mas pode.
fonte
Os aplicativos Windows Forms normalmente têm um ponto de entrada parecido com este:
Se você definir esse ponto no código como sua raiz de composição , poderá reduzir bastante o número de locais em que você tem código invocando explicitamente o Ninject como se fosse um Localizador de Serviço.
A partir deste ponto, você injeta todas as suas dependências via injeção de construtor.
Se sua "dependência" é algo que você precisa produzir várias vezes, o que você realmente precisa é de uma fábrica:
Você pode implementar a interface IFactory dessa maneira para evitar a necessidade de criar várias implementações pontuais:
fonte
InjectionFactory<T>
implementado, o código fornecido deve funcionar perfeitamente. Há algo em particular com o qual você está tendo problemas?Type
, mas que garantiria que os objetos hidratadosType
implementassem ou estendessem um determinado tipo genérico. Nada muito especial.Eu sempre escrevo um wrapper Adapter para qualquer Container IoC, que se parece com isso:
Para o Ninject, especificamente, a classe Adapter concreta é assim:
A principal razão para fazer isso é abstrair a estrutura da IoC, para que eu possa substituí-la a qualquer momento - dado que a diferença entre as estruturas geralmente está na configuração e não no uso.
Mas, como um bônus, as coisas também se tornam muito mais fáceis para o uso da estrutura de IoC em outras estruturas que não a suportam por natureza. Para o WinForms, por exemplo, são duas etapas:
No seu método Main, basta instanciar um contêiner antes de fazer qualquer outra coisa.
E, em seguida, tenha um formulário base, do qual derivam outros formulários, que chama o próprio Injetar.
Isso informa à heurística da fiação automática para tentar injetar recursivamente todas as propriedades no formulário que atendem às regras definidas em seus módulos.
fonte
O bom uso da injeção de dependência geralmente depende da separação do código que cria objetos e da lógica de negócios real. Em outras palavras, eu não gostaria que minha equipe usasse
new
e criasse uma instância de uma classe dessa maneira. Uma vez feito, não há como trocar facilmente esse tipo criado por outro, pois você já especificou o tipo concreto.Portanto, existem duas maneiras de corrigir isso:
TestClass
no seu Windows Form para que ele já tenha uma instância quando precisar. Quando o Ninject instancia seu formulário, ele cria automaticamente a dependência.IKernel
no Windows Form e usá-lo para instanciarTestClass
. Dependendo do seu estilo, existem outras maneiras de fazer isso (injetar uma classe de fábrica, um representante da fábrica, etc.).Isso facilita a troca do tipo concreto de TestClass e a construção real da classe de teste, sem modificar o código que usa a classe de teste.
fonte
Eu não usei o Ninject, mas a maneira padrão de criar coisas quando você está usando uma IoC é através de um
Func<T>
where ondeT
é o tipo de objeto que você deseja criar. Portanto, se o objetoT1
precisar criar objetos do tipoT2
, o construtor deT1
deve ter um parâmetro do tipoFunc<T1>
que será armazenado como um campo / propriedade deT2
. Agora, quando você deseja criar objetos do tipoT2
,T1
invoca oFunc
.Isso o separa totalmente da sua estrutura de IoC e é o caminho certo para codificar em uma mentalidade de IoC.
A desvantagem de fazer isso é que isso pode ser irritante quando você precisa conectar manualmente
Func
s ou, por exemplo, quando o criador exige algum parâmetro, para que a IoC não consiga instalar automaticamenteFunc
para você.http://code.google.com/p/autofac/wiki/RelationshipTypes
fonte