como escrever bibliotecas sem forçar os usuários a usar o contêiner IOC da biblioteca

A pergunta curta é: Dada uma biblioteca warrants usando um contêiner IOC específico para seus internos, quando um aplicativo consome essa biblioteca, dado o aplicativo warrants usando um contêiner do COI para conectar suas dependências, dado que os dois contêineres são diferentes, como eles podem funcionar bem junto

O cenário é que o aplicativo possui classes definidas que dependem dos tipos da biblioteca. Portanto, quando o contêiner do aplicativo tenta criar essa classe, ele precisa saber como resolver o tipo que vive na bibliotec

Aqui está a longa pergunta:

Esta pergunta parece ter sido feita em diferentes formas e formas antes no SO, mas não consigo encontrar a resposta necessária, por isso vou tentar com um exemplo concreto _over_simplified_ hipotético. Queremos escrever uma biblioteca para registro que os usuários possam incluir como um pacote em sua solução para obter a funcionalidade de registro pronta para uso. As interfaces públicas expostas pela biblioteca são ..

public interface ILogger {}

public interface ITarget {}

s implementações de concreto são

internal class Logger: ILogger { public Logger(ITarget target) {}}

internal class FileTarget : ITarget {}

Requirements são se o usuário incluir nosso pacote e definir uma classe com uma propriedade do tipoILogger ou tem um argumento ctor do tipoILogger, nossa biblioteca é responsável por injetar uma implementação concreta para essa interface na classe definida pelo usuário. Por padrão, o log injetado irá para o sistema de arquivos para log porque a implementação padrão de umITarget injetado noILogger implementação é umFileTarget pela nossa biblioteca.

Se o usuário decidir escrever uma classe implementando oITarget, nossa biblioteca usará isso para injetar noLogger class e não use seu padrãoFileTarget implementação.

SO que eu quero demonstrar é que é uma dependência bidirecional aqu

nossa biblioteca depende dos assemblies do usuário, pois precisa varrer os assemblies do usuário para carregar quaisquer pontos de extensão (ou seja, umITarget implementação) e injete-os em seus próprios objetos antes de qualquer implementação padrã

Os assemblies do usuário dependem da biblioteca, pois se o usuário escolher definir uma classe com umILogger como uma dependência, esse objeto de usuário deve obter uma referência concreta a essa interface fornecida em tempo de execução por nossa bibliotec

A solução fácil é que, se o usuário e nossa biblioteca estiverem usando o mesmo contêiner IOC, o problema será resolvido. Mas essa é uma forte suposição. O que eu desejo fazer é

Use um contêiner de COI com a biblioteca que atenda melhor aos requisitos da biblioteca, no meu caso, o Ninjec No tempo de execução, de alguma forma, forneço um mecanismo para o usuário chamar por meio de uma API na minha biblioteca que garantirá que o Ninject seja acionado e verifique os assemblies do usuário e conecte tudo, levando em consideração todos os pontos de extensão.

té aqui tudo bem, é perfeitamente possível, mas aqui vem a parte complicad

se o usuário também estiver usando o Ninject, o problema será resolvido automaticamente, pois o Ninject já sabe como resolver as interfaces que vivem em nossa biblioteca. Mas e se o usuário decidir usar sua opção de contêiner IOC?

Quase quero definir algum tipo de funcionalidade de contêiner filho na biblioteca com uma interface como essa

public interface IDependencyResolvingModule { T Get<T>(); []T GetAll<T>(); }

e forneça uma implementação que use a opção de contêiner da nossa biblioteca (ou seja, Ninect) para resolver o tipo solicitado nos dois métodos definidos acima.

Eu quero que o contêiner IOC do usuário tenha alguma funcionalidade em que, se não puder resolver uma dependência (ou seja, umILogger), ele deve se conectar aoIDependencyResolvingModule implementação e solicite a dependênci

Dessa maneira, nossa biblioteca usa sua opção de contêiner IOC, e o código do usuário tem uma maneira de resolver dependências das quais seu contêiner IOC não tem idéia. Essa solução não funcionaria se os contêineres de IOC existentes tivessem alguma funcionalidade fornecida para registrar instâncias singleton de qualquerIDependencyResolverModules encontrado em assemblies no diretório do assembly em execução e, quando eles não conseguem resolver um tipo, pergunte a qualquer um dos módulos singleto

Mas, com exceção de uma solução que exige que todos os outros contêineres do COI sejam acomodados, de que outra forma isso pode ser resolvido? Portanto, o problema em algumas linhas é que, quando um assembly de terceiros opta por usar um contêiner IOC para seus internos, o que é uma solução fácil, de modo que esta biblioteca pode simplesmente fornecer um mecanismo para um contêiner IOC sentado do lado de fora para conectar e resolver dependências que vivem na biblioteca.

questionAnswers(2)

yourAnswerToTheQuestion