Comment conciliez-vous IDisposable et le Cio?
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é?
- Ma solution est d'utiliser un Cio avec bon et bien codifiées gestion de durée de vie: AutoFac et le Château de Windsor ont, par exemple (bien qu'ils fonctionnent un peu différemment); Unité 2.1 simplement échoue lorsque vous traitez avec des transitoires en vertu de la durée de vie par défaut gestionnaires ..
Vous devez vous connecter pour publier un commentaire.
AutoFac poignées en autorisant la création d'un conteneur imbriqué. Lorsque le conteneur est fini avec, automatiquement, il dispose de tous les IDisposable objets. Plus ici.
container.Release
méthodeVous 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 est d'envelopper votre objet non géré dans certains géré interface:
C'est juste un exemple, je voudrais utiliser Fichier.ReadAllText(chemin) si je devais essayer de lire un fichier texte dans une chaîne de caractères.
Une autre approche consiste à injecter une usine et de gérer l'objet vous-même:
Ce a me laisse perplexe souvent. Si pas heureux à ce sujet, je suis toujours à la conclusion que jamais de retour d'un IDisposable objet dans un transitoire de la façon qui était le mieux.
Récemment, j'ai reformulé la question pour moi-même: Est-ce vraiment un Cio problème, ou une .net framework problème? L'élimination est difficile de toute façon. Il n'a pas de sens objectif fonctionnel, seulement technique. Il est donc plus une question cadre que nous avons à traiter avec, que du Cio problème.
Ce que j'aime à propos de DI est ce que je peux demander un contrat de m'offrir des fonctionnalités, sans avoir à se soucier des détails techniques. Je ne suis pas le propriétaire. Aucune connaissance de la couche sur laquelle il est en. Pas de connaissances concernant les technologies qui sont nécessaires pour remplir le contrat, pas de soucis à propos de la durée de vie. Mon code a l'air sympa et propre, et il est très testable. Je peux mettre en œuvre des responsabilités dans les couches où ils appartiennent.
Donc si il y a une exception à cette règle, ce qui ne m'obligent à organiser la vie, faisons en sorte que cette exception. Si je l'aime ou pas. Si l'objet qui implémente l'interface m'oblige à mettre au rebut, je veux savoir à ce sujet depuis que je suis déclenchée à utiliser l'objet de la plus courte possible. Un truc de le résoudre à l'aide d'un conteneur enfant qui est disposé quelques temps plus tard pourrait encore me causer de garder l'objet en vie plus longtemps que je ne l'. Le permis de durée de vie de l'objet est déterminé lors de l'enregistrement de l'objet. Pas par la fonctionnalité qui crée un conteneur enfant et tient pour une certaine période.
Tant et aussi longtemps que nous, développeurs, besoin de s'inquiéter à propos de l'élimination (va jamais changer?) Je vais essayer d'injecter quelques transitoire jetables d'objets que possible.
1. J'essaie de faire de l'objet n'est pas IDisposable, par exemple, ne pas garder les objets jetables sur le niveau de la classe, mais dans une moindre portée.
2. J'essaie de faire l'objet réutilisables ainsi qu'une durée de vie de manager peut être appliquée.
Si cela n'est pas possible, j'utilise une usine pour indiquer que l'utilisateur de l'injection de contrat est propriétaire et doit en assumer la responsabilité.
Il y a un problème: la modification d'un contrat de maître d'œuvre de non-jetables à usage unique sera d'une modification de rupture. À cette époque, l'interface ne sera plus enregistré, mais l'interface de l'usine. Mais je pense que cela s'applique à d'autres scénario est ainsi. Oublier d'utiliser un conteneur enfant sera à partir de ce moment, donner des problèmes de mémoire. L'usine approche entraîne un Cio résoudre exception.
Un exemple de code:
Je pense que, en général, la meilleure approche est tout simplement de ne pas Disposer de quelque chose qui a été injecté; vous devez supposer que l'injecteur est de faire de l'allocation et de désallocation.
ReleaseAndDisposeAllHttpScopedObjects
méthode. Vous avez encore besoin de comprendre comment les jetables vont être éliminés correctement... sauf si vous aimez courir de connexions et autres.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.
Mettre une façade en face du récipient peut résoudre ce ainsi. De Plus, vous pouvez l'étendre à garder une trace de la plus riche du cycle de vie comme le service des arrêts et des démarrages ou ServiceHost des transitions d'état.
Mon conteneur tend à vivre dans un IExtension qui implémente l'IServiceLocator interface. C'est la façade de l'unité, et permet un accès facile à des services WCf. En Plus je avoir accès au service d'événements de la ServiceHostBase.
Le code, vous vous retrouvez avec tenterons de voir si tout singleton enregistré ou n'importe quel type créé implémente une des interfaces, la façade conserve.
Ne permet pas encore de les disposer en temps opportun, comme vous, sont liés à ces événements, mais ça aide un peu.
Si vous voulez disposer en temps opportun (aka, maintenant c. s. lors de l'arrêt du service). Vous devez savoir que l'élément que vous obtenez est jetable, il fait partie de la logique métier pour s'en débarrasser, donc IDisposable devrait être une partie de l'interface de l'objet. Et il devrait probablement être la vérification des attentes untitests liées à la méthode dispose appelé.
Dans le cadre de l'Unité, il y a deux façons d'enregistrer les injecté classes: comme des singletons (vous obtenez toujours la même instance de la classe lorsque vous le résoudre), ou comme vous obtenez une nouvelle instance de la classe sur chaque résolution.
Dans ce dernier cas, vous avez la responsabilité de l'élimination de l'résolu instance une fois que vous n'en avez pas besoin (ce qui est tout à fait raisonnable). D'autre part, lorsque vous mettez le contenant (la classe qui gère objet de résolutions), tous les objets singleton sont automatiquement éliminés en tant que bien.
Par conséquent, il n'y a apparemment pas de problèmes d'injection jetable objets avec l'Unité du cadre. Je ne sais pas pour les autres cadres, mais je suppose que tant qu'une injection de dépendance cadre est assez solide, elle pour s'assurer que les poignées de cette question d'une façon ou d'une autre.