2010-01-14 5 views
3

Je programme par programme un groupe de services qui implémentent tous la même interface, IRule. J'ai un autre service qui ressemble à ceci:Comment enregistrer par programmation un composant qui dépend d'une liste de composants déjà enregistrés avec Castle Windsor?

public class MyService { 
    private IEnumerable<IRule> _rules; 
    public MyService(IEnumerable<IRule> rules){ 
     _rules = rules; 
    } 
} 

Hammett a posté quelque chose qui ressemblait à ce que je voulais, http://hammett.castleproject.org/?p=257. J'ai changé la signature en IRule [] et essayé l'astuce ArrayResolver dans le post mais cela n'a pas fonctionné pour moi (note, il n'a rien cassé non plus).

Quelqu'un sait comment enregistrer par programme un composant comme le code que j'ai posté ci-dessus?

+0

Voir ce post de Mike d'hier: http://mikehadlow.blogspot.com/2008/09 /resolving-arrays-with-windsor.html –

Répondre

2

J'ai chargé la source pour Castle.MicroKernel, et j'ai remarqué qu'il y a déjà un ArrayResolver et ListResolver (dans l'espace de noms Castle.MicroKernel.Resolvers.SpecializedResolvers). Le code que j'ai copié (à l'aveugle) du blog de Hammet n'a pas fonctionné, très probablement parce que le framework avait changé depuis qu'il avait été écrit.

Voici un exemple de projet démontrant comment faire: http://www.panteravb.com/downloads/WindsorCon.zip

J'ai essayé à la fois le ArrayResolver et ListResolver et ils ont tous deux travaillé sans accroc, il est assez simple, donc en supposant cette classe de service:

public class MyService 
{ 
    private IEnumerable<IRule> _rules; 
    public MyService(IList<IRule> rules) 
    { 
     _rules = rules; 
    } 
} 

vous pouvez enregistrer ce type comme ceci:

private IWindsorContainer _container; 
private void InitializeIoc() 
{ 
    _container = new WindsorContainer(); 
    _container.Kernel.Resolver.AddSubResolver(new ListResolver(_container.Kernel)); 
    _container.Register(Component.For<IRule>().ImplementedBy<Rule1>()); 
    _container.Register(Component.For<IRule>().ImplementedBy<Rule2>()); 
    _container.Register(Component.For<MyService>()); 
} 
+0

cela ne fonctionne pas pour moi – Miral

+0

cela a fonctionné, j'utilisais la liste plutôt qu'IList Miral

+0

Grande réponse Chris. Merci. Soumis une modification pour le rendre plus clair. Je pense que ça devrait être la meilleure réponse. –

6

Si vous ne voulez pas changer la signature de MyService et de garder en utilisant IEnumerable<IRule>, vous pouvez également créer un ISubDependencyResolver personnalisé. C'est ce que nous avons fait:

public class EnumerableResolver : ISubDependencyResolver 
{ 
    private readonly IKernel kernel; 

    public EnumerableResolver(IKernel kernel) 
    { 
     this.kernel = kernel; 
    } 

    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     Type targetType = dependency.TargetType; 
     if (targetType == null) 
     { 
      throw new ArgumentException("TargetType property cannot be null", "dependency"); 
     } 

     if (targetType.IsGenericType && (targetType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) 
     { 
      Type service = targetType.GetGenericArguments()[0]; 
      return this.kernel.HasComponent(service); 
     } 
     return false; 
    } 

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     Type service = dependency.TargetType.GetGenericArguments()[0]; 
     Array array = this.kernel.ResolveAll(service, (IDictionary)null); 
     return Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { service }), new object[] { array }); 
    } 
} 

Il doit être enregistré avec le récipient comme celui-ci:

container.Kernel.Resolver.AddSubResolver(new EnumerableResolver(this.Kernel)); 
Questions connexes