Question

J'ai un objet qui implémente IDisposable qui est enregistré avec le conteneur Windsor et j'aimerais le supprimer afin que sa méthode Dispose soit appelée et que le prochain appel à Resolve recherche une nouvelle instance.

Est-ce que

container.Release(obj); 

appeler automatiquement Dispose () immédiatement? Ou dois-je faire

obj.Dispose();
container.Release(obj);

Impossible de trouver quoi que ce soit dans la documentation sur ce que fait exactement la version

MODIFIER: Voir ma réponse ci-dessous pour les résultats des tests que j'ai effectués. Maintenant, la question est la suivante: comment forcer le conteneur à libérer une instance d'un composant avec un cycle de vie singleton? Cela ne doit être fait qu’à un seul endroit et écrire un cycle de vie personnalisé semble bien trop lourd, n’y a-t-il pas de moyen de le faire?

Était-ce utile?

La solution

C’est quelque chose que je pense que les gens ne sont pas vraiment conscients de travailler avec le conteneur Windsor - en particulier le comportement souvent surprenant selon lequel des composants transitoires jetables sont retenus par le conteneur. conteneur pendant toute la durée de vie du noyau jusqu'à ce qu'il soit éliminé, à moins que vous ne les libériez vous-même - même si cela est documenté - consultez ici - mais pour citer rapidement:

  

le MicroKernel a une politique de publication pouvant être connectée et implémentée   routage pour disposer les composants. Le MicroKernel est livré avec trois implémentations d’IReleasePolicy:

     
      
  • AllComponentsReleasePolicy: suivez tous les composants pour appliquer l'élimination correcte lors de l'élimination de l'instance MicroKernel
  •   
  • LifecycledComponentsReleasePolicy: suivez uniquement les composants associés à un cycle de vie de mise hors service
  •   
  • NoTrackingReleasePolicy: n'effectue aucun suivi
  •   
     

Vous pouvez également mettre en œuvre votre propre politique de publication à l'aide de l'interface IReleasePolicy.

Vous trouverez peut-être plus facile de remplacer la stratégie par une stratégie NoTrackingReleasePolicy , puis de vous en débarrasser. Cela présente également un risque, mais si votre style de vie est largement transitoire (ou si votre conteneur votre demande est sur le point de fermer de toute façon) ce n’est probablement pas un gros problème. Rappelez-vous toutefois que tous les composants qui ont déjà été injectés avec le singleton contiendront une référence, vous risqueriez donc de causer des problèmes en essayant de "rafraîchir" vos singletons - cela semble être une mauvaise pratique, et je me demande si vous pouvez peut-être éviter de le faire en commençant par améliorer la manière dont vos applications sont assemblées.

D'autres approches consistent à créer un cycle de vie personnalisé avec sa propre implémentation de mise hors service (par conséquent, la publication du singleton conduirait à la suppression du composant, un peu comme le fait le cycle de vie transitoire).

Une autre solution consiste à enregistrer un décorateur pour votre service dans le conteneur avec un style de vie singleton, mais votre service sous-jacent réel est enregistré dans le conteneur avec un style de vie transitoire. Lorsque vous devez actualiser le composant, il suffit de supprimer le transitoire. composant sous-jacent détenu par le décorateur et remplacez-le par une instance fraîchement résolue (résolvez-le en utilisant la clé de composants, plutôt que le service, pour éviter de recevoir le décorateur) - cela évite les problèmes avec d'autres services singleton (qui ne sont pas "rafraîchis"). ;) de conserver les services obsolètes qui ont été éliminés, ce qui les rend inutilisables, mais nécessite un peu de casting, etc. pour que cela fonctionne.

Autres conseils

Cela dépend du mode de vie du composant que vous avez spécifié lors de l'ajout au conteneur.

Vous utiliseriez Release () si le mode de vie est mis en pool. Cela remet le composant dans le pool pour la prochaine extraction (l'objet n'est pas détruit, donc l'élimination serait mauvaise).

Si le mode de vie est transitoire, un nouvel objet est créé lorsque vous obtenez le composant. Dans ce cas, la mise au rebut dépend de vous et vous n'avez pas besoin d'appeler Release

.

Si le style de vie est Thread, le même composant est utilisé pour chaque thread, pas détruit.

Si le style de vie est Singleton, un seul composant est créé et n'est pas détruit.

Très probablement, vous utilisez des composants transitoires? (si vous souhaitez en disposer rapidement) dans ce cas, enveloppez-le simplement avec une utilisation et vous êtes prêt (ou appelez le vous-même quelque part)

using(ISomeService service = container.Resolve<ISomeService>())
{
 // Do stuff here
 // service.Dispose is automatically called 
}

Modifier - Oui, pour "actualiser". ou disposez et recréez votre singleton dont vous auriez besoin pour détruire le conteneur ou écrire un cycle de vie personnalisé. Faire un cycle de vie personnalisé n’est pas si difficile et garde la logique de le faire au même endroit.

Très bien, j'ai donc exécuté des tests et il semble que Container.Release () provoque implicitement la méthode Dispose () d'un IDisposable à s'exécuter uniquement si le mode de vie est transitoire (ce n'est probablement pas tout à fait correct mais le fait est que cela ne fera pas une sacrée chose si le style de vie est singleton).

Maintenant, si vous appelez Container.Dispose () , les méthodes jetables seront également appelées. Malheureusement, le noyau entier sera malheureusement éliminé et vous devrez rajouter tous les composants dans:

var container = new WindsorContainer();
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable
obj.DoSomething();
var obj2 = container.Resolve<MyDisposable>();  // Returns the same instance as obj
obj2.DoSomething();
container.Dispose();  // Will call the Disposable method of obj
// Now the components need to be added back in   
 container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj3 = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable

Heureusement, dans mon cas, je peux me permettre de simplement supprimer tous les composants et de les restaurer assez facilement. Cependant, cela n’est pas optimal.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top