ServiceContainer, IoC e objetos descartáveis

Tenho uma pergunta e vou marcar esta subjectivo, já que é nisso que eu acho que evolui, mais uma discussão. Espero algumas boas idéias ou alguns instigadores. Peço desculpas pela longa pergunta, mas você precisa conhecer o context

A questão é basicamente:

Como você lida com tipos concretos em relação aos contêineres IoC? Especificamente, quem é responsável por descartá-los, se eles precisam ser descartados, e como esse conhecimento é propagado para o código de chamada?

Você precisa que eles sejam IDisposable? Caso contrário, esse código é à prova de futuro ou é a regra que você não pode usar objetos descartáveis? Se você impõe que os requisitos de IDisposable em interfaces e tipos concretos sejam à prova de futuro, cuja responsabilidade são os objetos injetados como parte das chamadas do construtor?

Edita: Aceitei a resposta por@ Chris Ballard, já que é a mais próxima da abordagem com a qual acabamo

Basicamente, sempre retornamos um tipo assim:

public interface IService<T> : IDisposable
    where T: class
{
    T Instance { get; }
    Boolean Success { get; }
    String FailureMessage { get; } // in case Success=false
}

Retornamos um objeto que implementa essa interface de volta a partir de .Resolve e .TryResolve, para que o que obtemos no código de chamada seja sempre do mesmo tipo.

gora, o objeto que implementa essa interface,IService<T> é IDisposable e devesempr ser descartado. Não cabe ao programador que resolver um serviço decidir se oIService<T> objeto deve ser descartado ou nã

Entretanto, e esta é a parte crucial, se a instância do serviço deve ser descartada ou não, esse conhecimento é incorporado ao objeto que implementaIService<T>, portanto, se for um serviço de escopo de fábrica (ou seja, cada chamada para Resolver terminar com uma nova instância de serviço), a instância de serviço será descartada quando oIService<T> objeto é descartad

@This também possibilitou o suporte a outros escopos especiais, como pool. Agora, podemos dizer que queremos no mínimo 2 instâncias de serviço, no máximo 15 e tipicamente 5, o que significa que cada chamada para .Resolve recuperará uma instância de serviço de um pool de objetos disponíveis ou criará uma nova. E então, quando oIService<T> o objeto que mantém o serviço em pool é descartado, a instância do serviço é liberada novamente em seu poo

Claro, isso fez com que todo o código fosse assim:

using (var service = ServiceContainer.Global.Resolve<ISomeService>())
{
    service.Instance.DoSomething();
}

mas é uma abordagem limpa e tem a mesma sintaxe, independentemente do tipo de serviço ou objeto concreto em uso, por isso escolhemos isso como uma solução aceitáve

Pergunta original a seguir, para a posteridade

Pergunta longa vem aqui:

Temos um contêiner de IoC que usamos e recentemente descobrimos o que significa um problem

No código não IoC, quando queríamos usar, digamos, um arquivo, usamos uma classe como esta:

using (Stream stream = new FileStream(...))
{
    ...
}

Não havia dúvida se essa classe era ou não um recurso limitado, pois sabíamos que os arquivos tinham que ser fechados e a própria classe implementava IDisposable. A regra é simplesmente que toda classe da qual construímos um objeto, que implementa IDisposable, deve ser descartada. Sem perguntas. Não cabe ao usuário desta classe decidir se chamar Dispose é opcional ou nã

Ok, prossiga para o primeiro passo em direção ao contêiner de IoC. Vamos supor que não queremos que o código fale diretamente com o arquivo, mas passemos por uma camada de indireção. Vamos chamar essa classe de BinaryDataProvider para este exemplo. Internamente, a classe está usando um fluxo, que ainda é um objeto descartável; portanto, o código acima seria alterado para:

using (BinaryDataProvider provider = new BinaryDataProvider(...))
{
    ...
}

Isto não muda muito. O conhecimento que a classe implementa IDisposable ainda está aqui, sem perguntas, precisamos chamar Dispose.

Mas, vamos assumir que temos classes que fornecem dados que no momento não usam esses recursos limitado

O código acima poderia então ser escrito como:

BinaryDataProvider provider = new BinaryDataProvider();
...

OK, até agora tudo bem, mas aqui vem a carne da pergunta. Vamos supor que queremos usar um contêiner de IoC para injetar esse provedor, em vez de depender de um tipo concreto específic

O código seria então:

IBinaryDataProvider provider =
    ServiceContainer.Global.Resolve<IBinaryDataProvider>();
...

Note que presumo que exista uma interface independente disponível, pela qual possamos acessar o objet

Com a alteração acima, e se mais tarde desejarmos usar um objeto que realmente deve ser descartado? Nenhum código existente que resolve essa interface é gravado para descartar o objeto, e agor

Da maneira que vemos, temos que escolher uma solução:

verificação do tempo de execução do @Implement que verifica se um tipo concreto que está sendo registrado implementa IDisposable, exige que a interface pela qual ele é exposto também implemente IDisposable. Esta não é uma boa soluçãoAntes de haver uma restrição nas interfaces que estão sendo usadas, elas sempre devem herdar de IDisposable, para serem à prova de futuroEnforce o tempo de execução que nenhum tipo concreto pode ser descartável por ID, pois isso não é tratado especificamente pelo código usando o contêiner IoC Apenas deixe ao programador verificar se o objeto implementa IDisposable e "faça a coisa certa" Existem outros?

Além disso, o que dizer de injetar objetos em construtores? Nosso container, e alguns dos outros containers que examinamos, são capazes de injetar um novo objeto em um parâmetro para um construtor de um tipo concreto. Por exemplo, se nossoBinaryDataProvider precisa de um objeto que implemente oILogging interface, se aplicarmos IDispose- "habilidade" nesses objetos, de quem é a responsabilidade de descartar o objeto de lo

O que você acha? Quero opiniões, boas e má

questionAnswers(3)

yourAnswerToTheQuestion