2009-03-16 7 views
2

Compte tenu de la configuration ci-dessousWindsor Castle API Courant: Définir la dépendance explicitement

 Container.Register(Component.For<A>().Named("foo")); 
     Container.Register(Component.For<B>().Named("foobar")); 

     Container.Register(
      AllTypes.Pick() 
      .FromAssemblyNamed("MyAssembly") 
      .If(t => t.Name.EndsWith("ABC")) 
      .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)) 
      .WithService.Select(i => typeof(I)) 
     ); 

     Container.Register(
      AllTypes.Pick() 
      .FromAssemblyNamed("MyAssembly") 
      .If(t => t.Name.EndsWith("123")) 
      .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)) 
      .WithService.Select(i => typeof(I)) 
     ); 

Si je sais que l'interface "I" expose une propriété "P", et que les classes A et B peut être affecté à P ; comment je déclare explicitement que la première collection de types de l'appel AllTypes doit avoir la propriété P définie sur le type avec l'ID de "foo", et la deuxième collection doit avoir la même propriété définie sur le type avec l'ID de "foobar "? En utilisant XML config, ceci peut être fait en définissant explicitement les paramètres en utilisant la notation $ {id}. Je suppose que c'est similaire dans l'API fluide.

Merci.

Répondre

2

Vous êtes sur la bonne voie - ce que vous devez faire est de configurer les paramètres de chaque composant, en fournissant le paramètre "P" avec la valeur "$ {foo}" ou "$ {foobar}" en fonction de votre scénario, voici un fait qui fonctionne (faites défiler vers le bas pour le code d'enregistrement réel) qui montre votre scénario.

namespace Question651392 
{ 
    public class First123 : I 
    { 
    public AbstractLetter P { get; set; } 
    } 

    public class Second123 : I 
    { 
    public AbstractLetter P { get; set; } 
    } 

    public class FirstABC : I 
    { 
    public AbstractLetter P { get; set; } 
    } 

    public class SecondABC : I 
    { 
    public AbstractLetter P { get; set; } 
    } 

    public interface I 
    { 
    AbstractLetter P { get; set; } 
    } 

    public abstract class AbstractLetter 
    { 
    } 

    public class B : AbstractLetter 
    { 
    } 

    public class A : AbstractLetter 
    { 
    } 

    public class RegistrationFacts 
    { 
    [Fact] 
    public void EnsureParametersCanBeSetWhenRegisteringComponentsInBulk() 
    { 
     WindsorContainer Container = new WindsorContainer(); 

     Container.Register(Component.For<A>().Named("foo")); 
     Container.Register(Component.For<B>().Named("foobar")); 

     Container.Register(
      AllTypes.Pick() 
      .FromAssembly(GetType().Assembly) 
      .If(t => t.Name.EndsWith("ABC")) 
      .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)) 
      .Configure(c=>c.Parameters(Parameter.ForKey("P").Eq("${foo}"))) 
      .WithService.Select(new[] { typeof(I) })   
    ); 

     Container.Register(
      AllTypes.Pick() 
      .FromAssembly(GetType().Assembly) 
      .If(t => t.Name.EndsWith("123")) 
      .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)) 
      .Configure(c => c.Parameters(Parameter.ForKey("P").Eq("${foobar}"))) 
      .WithService.Select(new[] { typeof(I)}) 
    ); 

     var all = Container.ResolveAll<I>(); 

     var firstABC = all.Single(i => i is FirstABC); 
     Assert.IsType(typeof(A), firstABC.P); 

     var first123 = all.Single(i => i is First123); 
     Assert.IsType(typeof (B), first123.P); 

     Assert.Equal(4, all.Count()); 
    } 
    } 
} 

Espérons que cela aide!

1

Une chose à mentionner lors des tests.

Le deuxième appel à configurer semble annuler le premier appel.

 .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)) 
     .Configure(c => c.Parameters(Parameter.ForKey("P").Eq("${foobar}"))) 

Si vous ajoutez à l'épreuve

 var all2 = Container.ResolveAll<I>(); 
     Assert.IsTrue(all.Count(i => all2.Contains(i)) == 0); 

il échouera, mais on peut s'y attendre, il passe trop que tout est déclarée transitoire. Cela implique que le mode de vie transitoire a été perdu et que le mode de vie par défaut de singleton a été utilisé à la place.

La modification de l'appel de configuration au résultat ci-dessous entraîne une passe de test.

 .Configure(c => .LifeStyle.Is(LifestyleType.Transient).Parameters(Parameter.ForKey("P").Eq("${foobar}"))) 

Merci.

+0

Vous avez raison - je ne sais pas si ce comportement idéal de la part de l'enregistrement courant - pouvoir Remplacer une configuration précédente est pratique dans certains scénarios, mais probablement un peu inattendu dans la plupart des cas! – Bittercoder

1

En fait, pour ajouter à @ réponse complète de Bittercoder, la méthode recommandée pour le faire est:

.DependsOn(Property.ForKey("P").Is("fooBar")) 
Questions connexes