CoreLib ObjectFactory Design Reference
Keyworks: ObjectFactory Container Dependency Injection IoC Inversion Control Service Locator SimpleInjector Unity
Introdução
Num produto complexo a instanciação dos objetos pode tornar-se um problema de manutenção porque as dependências tendem a evoluir e é muito fácil introduzir uma quebra. Uma solução é delegar o problema da instanciação para um componente que conhece todos os outros e sabe criar e resolver as suas instâncias.
Desenho
O container deixa de ser o tipo amplamente usado e passa a estar escondido por detrás de uma Façade construída com base nos tipos estáticos e por isso deixa de estar acessível fora dos componentes CoreLib.
A implementação atual usa um container interno implementado usando o SimpleInjector.
Instanciação de Objetos
Para criar objetos simples que não são registados no Container mas que têm interesse em ver as suas dependências iniciadas:
- ObjectFactory.Get
();
CustomerViewModel myViewModel = ObjectFactory.Get<CustomerViewModel>();
Para obter a instância correta de um dado tipo:
- ObjectFactory.Get
();
public property IMyType MyProperty
{
get
{
return ObjectFactory.Get<IMyType>();
}
}
Registo de Tipos
- ObjectFactoryConfiguration.Register
(); - ObjectFactoryConfiguration.Register
(RegistrationOption.IfMissing, Replace); - ObjectFactoryConfiguration.Register
(Lifecycle.AlwaysCreateNew, Singleton);
RegistrationOption
Esta opção do registo permite controlar o registo de vários tipos para o mesmo contrato:
- IfMissing – o registo será efetuado apenas se não existir um anterior para o mesmo contrato.
- RegisterOrReplace – o registo substituirá um anterior se existir.
- RegisterMultiple – o registo é incrementado a qualquer outro que já exista para o mesmo tipo. Nesse caso, a resolução deverá ser realizada através do método GetAll.
Lifecycle
Esta opção permite controlar o ciclo de vida da instância concreta devolvida na resolução.
- AlwaysCreateNew – será devolvida uma nova instância do tipo em cada resolução.
- Singleton – será devolvida sempre a mesma instância do tipo a cada resolução.
Limitações
- Dado o desenho do container interno, todos os registos de tipos deve acontecer antes do primeiro Get. Sempre que um registo for invocado depois do primeiro get resolvido, será lançada uma exceção e o registo falhará.
- O componente não suporta qualquer tipo de mecanismo de registo por convenção. Ou seja, um Get só devolverá um resultado se existir um registo explícito para esse tipo feito anteriormente. Exceto o caso em que o tipo solicitado seja uma classe (não uma interface) porque nesse caso será devolvida uma instância desse mesmo tipo (o que facilita o cenário descrito acima de inicialização de dependências desse tipo).
Configuração
Este componente foi desenhado para ser usado programaticamente. No entanto, é possível incluir no ficheiro de configuração registos de tipos que serão realizados automaticamente no momento em que o componente for ativado pela primeira vez.
Esses registos devem identificar claramente os tipos do contrato e da implementação, usando o assembly qualified name.
Exemplo:
<objectFactoryConfiguration>
<types>
<add typeName="Company.Contracts.IYourOtherType, Company.Contracts, Version=3.0.0.0, Culture=neutral, PublicKeyToken=33086db60a481256" concreteType="Company.Domain.YourOtherType, Company.Domain, Version=3.0.0.0, Culture=neutral, PublicKeyToken=33086db60a481256"/>
</types>
</objectFactoryConfiguration>
Tracing
O comportamento deste componente pode ser diagnosticado ativando o modo Verbose do componente de Tracing da plataforma.
<tracingConfiguration level="Verbose">
FAQ
- P: Em que momento é efetuado o registo dos tipos enumerados no ficheiro de configuração?
- R: Exatamente no primeiro instante em que o componente seja usado, seja através de um
ObjectFactoryConfiguration.Registerou através de umObjectFactory.Get.
- R: Exatamente no primeiro instante em que o componente seja usado, seja através de um
- P: O que acontece se fizer um Get de um tipo não registado?
- R: Se o tipo for uma interface, será devolvido null ou lançada uma exceção (dependendo de um parâmetro do Get). Se for uma classe será devolvida uma instância dessa mesma classe.