Pergunta

Eu estou usando Unity da Microsoft para injeção de dependência e eu quero fazer algo como isto:

IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context

IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);

RepositoryA e RepositoryB ambos têm um construtor que leva um parâmetro IDataContext, e eu quero Unity para inicializar o repositório com o contexto que eu passá-lo. Observe também que IDataContext não está registrado com Unity (Eu não quero 3 casos de IDataContext).

Foi útil?

Solução

A partir de hoje eles acrescentaram esta funcionalidade:

É na última gota aqui:

http://unity.codeplex.com/SourceControl/changeset/view/33899

Discussão sobre ele aqui:

http://unity.codeplex.com/Thread/View.aspx? ThreadId = 66434

Exemplo:

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"

Outras dicas

<2 centavos>

E se você mais tarde decidir usar um serviço diferente, que exige mais ou menos do que apenas o contexto?

O problema com parâmetros do construtor e COI é que os parâmetros são finalmente ligado ao tipo de betão que está sendo utilizado, em vez de ser parte do contrato que a define a interface de serviço.

A minha sugestão seria que você quer resolver o contexto assim, e eu acredito Unity deve ter uma maneira de evitar a construção de 3 casos do mesmo, ou você deve considerar um serviço de fábrica que tem uma forma de você para construir o objeto.

Por exemplo, se você mais tarde decidir construir um repositório que não depende de um banco de dados tradicional em tudo, mas sim usar um arquivo XML para produzir dummy-dados para o teste? Como você iria sobre a alimentação do conteúdo XML para esse construtor?

IoC é baseado em torno de desacoplamento código, amarrando no tipo e semântica dos argumentos para os tipos de concreto, você realmente não têm feito o desacoplamento corretamente, ainda há uma dependência.

"Este código pode conversar com qualquer tipo de repositório, possivelmente, desde que implementa essa interface .... Oh, e usa um contexto de dados".

Agora, eu sei que outros recipientes de IoC tem suporte para isso, e eu tinha em minha primeira versão do meu próprio bem, mas na minha opinião, ele não pertence a etapa resolução.

Obrigado rapazes ... o meu é semelhante à mensagem por "existe". Veja abaixo:

        IUnityContainer container = new UnityContainer();
        container.LoadConfiguration();

        _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
        {
            new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
        });

Você pode usar InjectionConstructor / InjectionProperty / InjectionMethod dependendo do seu Injection Arquitetura dentro da ResolvedParameter ( "nome") para obter uma instância de um objeto pré-registrada no recipiente.

No seu caso este objeto deve ser registrado com um nome, e para o mesmo insance você precisa ContainerControlledLifeTimeManager () como o LifeTimeManager.

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");

  var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));

A resposta muito curta é: não. Unidade tem atualmente nenhuma maneira de passar parâmetros para o construtor que não são constantes ou injetada, que eu tenho sido capaz de encontrar. IMHO que é a única coisa mais importante que está faltando, mas eu acho que é próprio do projeto e não por omissão.

notas Como Jeff Fritz, você poderia, em teoria, criar um gerenciador de vida personalizado que sabe qual instância de contexto para injetar em vários tipos, mas isso é um nível de codificar que parece evitar o propósito de usar Unity ou DI no primeiro Lugar, colocar.

Você poderia dar um pequeno passo para trás de DI completa e faça as suas implementações de repositórios responsável por estabelecer os seus próprios contextos de dados. O contexto exemplo pode ainda ser resolvido a partir do recipiente, mas a lógica para decidir qual uso teria que ir para a implementação do repositório. Não é tão puro, certamente, mas que iria se livrar do problema.

Outra alternativa você pode usar (realmente não sei se é uma boa prática ou não) é a criação de dois recipientes e registrar uma instância para cada:

IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context


//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

espero que isso ajude muito

NotDan, eu acho que você pode ter respondido à sua própria pergunta nos comentários para lassevk.

Em primeiro lugar, gostaria de usar um LifetimeManager para gerenciar o ciclo de vida eo número de casos de IDataContext que a Unidade cria.
http://msdn.microsoft.com/en-us/library/cc440953. aspx

Parece que o objeto ContainerControlledLifetimeManager lhe dará o gerenciamento de instância que você precisa. Com isso LifetimeManager no lugar, Unidade deve adicionar a mesma instância do IDataContext a todos os objetos que requerem uma dependência IDataContext.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top