2008-09-17 7 views
9

J'ai un objet qui implémente IDisposable qui est enregistré avec le conteneur Windsor et je voudrais en disposer pour que sa méthode Dispose soit appelée et la prochaine fois que Resolve est appelée, elle récupère une nouvelle instance.Windsor Container: Comment forcer l'élimination d'un objet?

Est-ce que

container.Release(obj); 

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

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

Impossible trouver quelque chose dans la documentation sur exactement ce communiqué ne

EDIT: Voir ma réponse ci-dessous les résultats des tests que je courais. Maintenant, la question devient, comment puis-je forcer le conteneur à libérer une instance d'un composant avec un cycle de vie singleton? Cela doit seulement être fait en un seul endroit et écrire un cycle de vie personnalisé semble beaucoup trop lourd, n'est-il pas construit de façon à le faire?

Répondre

10

C'est quelque chose que je pense que les gens ne sont pas vraiment au courant lorsque l'on travaille avec le conteneur Windsor - en particulier le souvent comportement surprenant que les composants transitoires à usage unique sont maintenus sur le conteneur pour la durée de vie du noyau jusqu'à ce qu'il soit disposé à moins que vous les libérer vous-même - mais il est documenté - jetez un oeil here - mais de citer rapidement:

le micronoyau a une politique de libération connectables qui peut brancher et mettre en œuvre un certain routage pour éliminer les composants. Le MicroKernel est livré avec trois implémentations IReleasePolicy:

  • AllComponentsReleasePolicy: suivre tous les composants pour appliquer l'élimination correcte lors de la cession d'instance MicroKernel
  • de LifecycledComponentsReleasePolicy: suivre uniquement les composants qui ont un cycle de vie de désaffecter associés
  • NoTrackingReleasePolicy: ne fonctionne pas tout suivi

Vous pouvez également implémenter votre propre stratégie de version à l'aide de l'interface IReleasePolicy.

Ce que vous trouverez peut-être plus facile est de changer la politique à un NoTrackingReleasePolicy puis gérer l'élimination vous - c'est potentiellement risqué bien, mais si votre mode de vie sont en grande partie transitoire (ou si lorsque votre réservoir est disposé votre application est sur le point de fermer de toute façon) ce n'est probablement pas une grosse affaire. Souvenez-vous cependant que tous les composants qui ont déjà été injectés avec le singleton contiendront une référence, donc vous pourriez finir par causer des problèmes en essayant de "rafraîchir" vos singletons - cela semble être une mauvaise pratique, et je me demande si vous pouvez éviter faites cela en premier lieu en améliorant la manière dont vos applications sont mises ensemble.

D'autres approches consistent à construire un cycle de vie personnalisé avec sa propre implémentation de mise hors service (libérer ainsi le singleton éliminerait le composant, comme le fait le cycle de vie transitoire). Une autre approche consiste à avoir un décorateur pour votre service enregistré dans le conteneur avec un style de vie singleton, mais votre service sous-jacent réel enregistré dans le conteneur avec un mode de vie transitoire - puis lorsque vous avez besoin de rafraîchir le composant juste disposer du le composant sous-jacent transitoire retenu par le décorateur et le remplacer par une instance fraîchement résolue (résolvez-la en utilisant la clé composants, plutôt que le service, pour éviter d'avoir le décorateur) - cela évite les problèmes avec d'autres services singleton ") de détenir des services périmés qui ont été éliminés les rendant inutilisables, mais nécessite un peu de coulée, etc. pour que cela fonctionne.

+0

J'ai un problème similaire, j'aime beaucoup le concept de décorateur. Nice one ... –

+0

@Bittercoder si je dispose le conteneur appellera-t-il disposer d'objets singleton comment le forcer? –

3

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

Vous utiliseriez Release() si le style de vie est Pooled. Cela remet le composant dans le pool pour la récupération suivante (l'objet n'est pas détruit, donc l'élimination serait mauvaise)

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

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

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

Très probablement, vous utilisez des composants transitoires? (Si vous êtes préoccupé par l'élimination d'entre eux en temps opportun) dans ce cas, il suffit de l'envelopper avec l'aide et vous définissez (ou appelez vous-même quelque part en disposer)

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

Modifier - Oui , pour "rafraîchir" ou disposer et recréer votre singleton, vous devez détruire le conteneur ou écrire un cycle de vie personnalisé. Faire un cycle de vie personnalisé n'est pas vraiment difficile et maintient la logique de le faire en un seul endroit.

+0

En fait, je fais des singletons mais je voudrais le forcer à régénérer le composant de temps en temps. –

1

D'accord, donc j'ai l'exécution des tests et il semble que Container.Release() WILL implicitement provoquer Dispose() méthode d'un IDisposable pour exécuter uniquement si le mode de vie est transitoire (ce qui est probablement pas tout à fait correct, mais le point est que ce wont faire une sacrément chose si le style de vie est singleton).

Maintenant, si vous appelez Container.Dispose() il appellera les méthodes à usage unique aussi, mais il sera malheureusement éliminer tout le noyau et vous devez ajouter tous les composants retour 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 se permettre de laisser tomber tous les composants et je peux les restaurer assez facilement. Cependant, ceci est sous-optimal.

Questions connexes