2012-03-22 3 views
2

Je dois souligner que je suis relativement nouveau à Castle, donc je ne sais pas vraiment ce que je fais avec. L'essentiel, c'est que j'essaie de faire un cycle de vie personnalisé d'un objet avec Castle Windsor. Je ne suis pas tout à fait sûr comment cela devrait être fait, cependant, l'approximation la plus proche que je peux trouver à la façon dont cela devrait fonctionner, j'ai détaillé ci-dessous.Castle dépendance injection Lifestyle

Je veux un singleton, mais je ne peux pas publier ce type et assigner une nouvelle instance à.

-à-dire,

public interface IMyObject { string text; } 

public class MyObject() : IMyObject { 
    public string text; 
} 

var container = new WindsorContainer(); 
container.Register(Component.For<IMyObject>().ImplementedBy<MyObject>().LifeStyle.Singleton); 

MyObject item = SomeMethodGetInstance(); //Defines scope for instance 1 
item = container.Resolve<IMyObject>(item); 
Print(item);  

>>instance 1 
.... 

item = container.Resolve<IMyObject>(); //gets instance 1 
Print(item); 
>>instance 1 
.... 

item = SomeMethodGetInstance() //New scope defined, now using instance 2 

Je veux être en mesure de libérer l'instance, mais Windsors définition d'un Singleton est trop rigide pour mes besoins.

container.Release(item); //I need to release the current instance, this doesn't work. 

ou

container.Kernal.ReleaseComponent(item); //Don't work either. 

Alors, quand je mets un nouvel élément que le courant ne revient pas à l'instance 1.

item = container.Resolve<IMyObject>(item); //sets the currect instance of MyObject 
Print(item); 

>>instance 2 

J'ai besoin de stocker une variable qui a une portée personnalisée, ni Singleton ni Transient vont couper la moutarde pour moi. Je dois pouvoir définir la portée, quand la variable stockée entre et sort de la portée. Plus précisément, si j'ai une autre classe B qui dépend de A, alors si j'obtiens A de l'extérieur du conteneur, comment définir A dans le conteneur? C'est bien dans un scénario singleton, mais je ne peux pas le définir pour un scénario transitoire, cependant, avec Singleton, une fois qu'il est défini, je ne peux pas le libérer, ce qui est nécessaire.

Comment est-ce que je fais ceci?

Je veux le faire en code plutôt qu'en XML, car j'inscris les classes dynamiquement.

+0

Vous pouvez créer un style de vie personnalisé en fonction de vos besoins. Voir l'exemple ici: http://stackoverflow.com/a/1366597/1275399 –

Répondre

0

Vous pouvez enregistrer votre composant en tant que simple comme suit

public void Register(string name, Type service, Type impl) 
{ 
    WindsorContainer container = new WindsorContainer(); 
    IKernel kernel = container.Kernel; 
    kernel.AddComponent(name, service, impl, LifestyleType.Singleton); 
} 

Vous pouvez libérer le composant comme suit

kernel.ReleaseComponent(yourResolvedSingletonInstance) 
+0

Un singleton ne peut pas être libéré. J'ai essayé l'implentation de registre que vous avez suggéré, mais cela ne fonctionne pas, Windsor n'aime pas le nom. – Craig

0

Je veux un singleton

Le style de vie par défaut pour Castle Windsor est singleton.

mais je ne peux pas libérer ce type et affecter une nouvelle instance à.

Mais ce n'est pas un singleton alors.

Comment est-ce que je fais ceci?

Vous n'avez pas spécifié exactement ce que vous voulez faire. Voulez-vous une nouvelle instance chaque fois que vous appelez Resolve? C'est LifeStyle.Transient.

+0

Ce n'est pas un singleton et ce n'est pas un transitoire, c'est une nuance de gris. J'utilise des objets récupérés d'une base de données. Il est clair pour moi, que ma mise en œuvre est un peu mauvaise, cependant, c'est ce dont j'ai besoin. L'approximation la plus proche est perWebRequest, mais je n'utilise pas http. – Craig

+1

Vous n'avez pas ** spécifié ** ce dont vous avez besoin. Vous devez le décrire ** précisément **. Vous ne parlez clairement pas en termes clairs parce que vous dites que vous voulez un singleton, mais vous ne le faites pas. Votre code indique qu'il devrait être quelque chose comme transitoire, mais vous ne dites pas. – jason

+0

J'ai un appel à la base de données, un objet est techniquement transitoire, mais je ne peux pas l'injecter dans d'autres classes car il est marqué comme transitoire, une nouvelle instance est créée à chaque fois, ce qui annule l'appel de base de données . Je ne peux pas marquer l'objet comme un singleton, car je ne peux pas alors faire de multiples extractions de l'objet, car je ne peux pas le libérer. – Craig

0

Avez-vous envisagé d'utiliser une fabrique personnalisée pour produire votre instance? Il peut invoquer l'infrastructure DI pour produire une nouvelle instance à chaque fois qu'il en a besoin, mais vous pouvez définir votre propre logique pour déterminer quand elle doit libérer une ancienne instance.

Cette approche répond également à votre deuxième question. La classe B ne doit pas prendre une A en tant que dépendance, mais plutôt un AFactory. Parce que B peut avoir une durée de vie plus longue que A, il doit demander à l'usine pour l'instance «en cours» de A chaque fois qu'il va l'utiliser.

+0

Cela pourrait être la voie à suivre. – Craig

+1

Non, ce n'est pas! Vous n'avez pas besoin d'un conteneur DI pour extraire des données d'une base de données, puis les transmettre à un consommateur de ces données. Vous compliquez inutilement les choses et vous ne vous achetez rien. Je pense que la réponse de StriplingWarrior a été faite avant qu'il ne connaisse le contexte dans lequel vous avez l'intention de l'utiliser. – jason

+0

Tout cela est très frustrant pour moi, c'est tout ce que je sais. – Craig