41 votes

Comment conciliez-vous IDisposable et IoC?

Je suis enfin enveloppant ma tête autour du Cio et DI en C#, et je suis aux prises avec certains des bords. Je suis l'aide de l'Unité de conteneur, mais je pense que cette question s'applique de façon plus générale.

À l'aide d'un conteneur IoC pour distribuer les instances qui mettent en œuvre des IDisposable me fait flipper! Comment êtes-vous censé savoir si l'on doit en Disposer()? L'instance peut avoir été créé juste pour vous (et à cet effet, vous devez Disposer ()), ou il pourrait être une instance dont la durée de vie est géré ailleurs (et à cet effet, vous feriez mieux de ne pas). Rien dans le code que vous avez dit, et en fait, cela pourrait changer en fonction de la configuration!!! Cela semble mortel pour moi.

Peut-Cio experts y décrire les bonnes façons de gérer cette ambiguïté?

17voto

Michael Valenty Points 5482

Vous ne voulez certainement pas appeler Dispose () sur un objet qui a été injecté dans votre classe. Vous ne pouvez pas supposer que vous êtes le seul consommateur. Votre meilleur pari consiste à envelopper votre objet non géré dans une interface gérée:

 public class ManagedFileReader : IManagedFileReader
{
    public string Read(string path)
    {
        using (StreamReader reader = File.OpenRead(path))
        {
            return reader.ReadToEnd();
        }
    }
}
 

Ce n'est qu'un exemple. J'utiliserais File.ReadAllText (path) si j'essayais de lire un fichier texte dans une chaîne.

Une autre approche consiste à injecter une usine et à gérer l’objet vous-même:

 public void DoSomething()
{
    using (var resourceThatShouldBeDisposed = injectedFactory.CreateResource())
    {
        // do something
    }
}
 

7voto

Samuel Jack Points 14556

AutoFac gère cela en permettant la création d'un conteneur imbriqué. Lorsque le conteneur est terminé, il supprime automatiquement tous les objets identifiables qu'il contient. Plus ici .

5voto

Lasse V. Karlsen Points 148037

Il y a essentiellement deux façons j'ai vu, c'est géré:

  1. Lorsque vous résolvez un service à un objet qui implémente IDisposable, le conteneur ne l'oubliez pas. Lorsque vous jetez le récipient, ce service va être éliminés en tant que bien.
  2. Lorsque vous résolvez un service, ce que vous obtenez en retour n'est pas seulement l'objet de service lui-même, mais vous obtenez également un objet wrapper, qui implémente IDisposable, et vous oblige à vous en débarrasser. Lorsque vous le faites, il permettra aussi de savoir quoi faire avec le réel de l'objet de service que vous avez demandé.

De la 2, la troisième est la plus commune:

  • Lorsque vous résoudre à un service qui mettent en œuvre des IDisposable, ne donnent pas une merde et il suffit de laisser le service objet flottant jusqu'à ce que la collecte des ordures gère.

C'est fondamentalement juste le Cio cadre pas vous fournir tous les moyens à tous de gérer ce problème. Si vous le faites, c'est votre cas, ne pas le cadre de la responsabilité.

Mais, attendez, le problème devient de plus en plus poilu, si vous le considérez.

Que faire si l'objet du service, vous obtenez en retour est un singleton? Même si cela peut mettre en œuvre IDisposable, devriez-vous vous en débarrasser? Comment savez-vous? Comment pouvez-vous le trouver? Pouvez - vous découvrir? Au moment où vous dites "je sais que ce service soit un singleton", vous avez en fait prendre une sorte de dépendance et mis en œuvre un code spécial pour le gérer. Le point de Cio est d'être capable de se substituer à des services sans changer le code qui les consume. IDisposable jette un gros bâton dans les roues de ce processus.

En bref, la meilleure solution avec la plupart des aujourd'hui Cio cadres est de mettre en place des services qui ne pas, mettre en oeuvre et nécessitent IDisposable.

2voto

Reed Copsey Points 315315

Cela dépend de la DI-cadre. Certains cadres vous permettent de spécifier si vous souhaitez une instance partagée (en utilisant toujours la même référence) pour chaque dépendance injecté. Dans ce cas, vous probablement ne voulez pas pour jeter.

Si vous pouvez préciser que vous souhaitez une instance unique injecté, alors vous voulez vous débarrasser (depuis qu'il a été construit pour vous en particulier). Je ne suis pas aussi familier avec l'Unité, tu devrais vérifier les docs quant à la façon de faire ce travail là. C'est une partie de l'attribut avec le MEF et quelques autres que j'ai essayé, pourtant.

2voto

Paul Sonier Points 25528

Je pense qu'en général, la meilleure approche consiste simplement à ne pas se débarrasser de quelque chose qui a été injecté; vous devez supposer que l'injecteur effectue l'allocation et la désallocation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X