2010-11-01 28 views
10

J'utilise Castle Windsor comme IoC container. J'ai une application qui a une structure similaire à ce qui suit:Castle Windsor: Inscrire automatiquement les types d'un ensemble qui implémente les interfaces d'un autre

  • MyApp.Services.dll
    • IEmployeeService
    • IContractHoursService
    • ...
  • MyApp.ServicesImpl.dll
    • EmployeeService : MyApp.Services.IEmployeeService
    • ContractHoursService : MyApp.Services.IContractHoursService
    • ...

-je utiliser le XML configuration au moment, et chaque fois que j'ajouter une nouvelle IService/paire de service, je dois ajouter un nouveau composant au XML fichier de configuration. Je veux passer tout cela à la fluent registration API mais je n'ai pas élaboré exactement la bonne recette pour faire ce que je veux pour le moment.

Quelqu'un peut-il aider? Les modes de vie seront tous singleton.

Merci beaucoup à l'avance.

Répondre

12

Avec AllTypes, vous pouvez facilement le faire:

De http://stw.castleproject.org/(S(nppam045y0sdncmbazr1ob55))/Windsor.Registering-components-by-conventions.ashx:

Enregistrer les composants un par un travail peut être très répétitif. Se rappeler également d'enregistrer chaque nouveau type que vous ajoutez peut rapidement mener à la frustration. Heureusement, vous n'avez pas à le faire, au moins toujours. En utilisant la classe d'entrée AllTypes, vous pouvez effectuer un enregistrement de groupe de types en fonction de certaines caractéristiques spécifiées que vous spécifiez.

Je pense que votre inscription ressemblerait à ceci:

AllTypes.FromAssembly(typeof(EmployeeService).Assembly) 
    .BasedOn<IEmployeeService>() 
    .LifeStyle.Singleton 

Si vous implémentez un type de base, comme IService sur vos interfaces, vous pouvez les enregistrer à la fois en utilisant la construction suivante:

AllTypes.FromAssembly(typeof(EmployeeService).Assembly) 
    .BasedOn<IService>() 
    .WithService.FromInterface() 
    .LifeStyle.Singleton 

Pour plus d'exemples, voir l'article. Cela a une très bonne description de ce que sont les possibilités.

+0

Cela ne fait pas 100% de ce dont j'ai besoin, cependant. Il y a différentes interfaces de service dans le premier assemblage, et j'ai un mappage un-un avec une instance concrète. Je devrais écrire le code ci-dessus encore et encore comme je le fais pour la config xml maintenant. –

+0

Est-ce une option d'avoir une interface de base pour 'IEmployeeService'? C'est ce que j'ai fait. Vous pouvez demander à Windsor de rechercher cette interface, enregistrez tout ce qui se trouve en dessous (donc, plus précisément, IEmployeeService) avec les implémentations de l'assembly. Élargi la réponse avec un exemple. –

+0

Vous voulez dire avoir un simple 'IService' avec aucun membre qui agit comme une interface de marqueur? Ça pourrait marcher, j'espérais juste pouvoir l'éviter. :) –

3

Je pris Pieter's answer avant juste un peu (la clé étant, comme il le suggère, AllTypes) et je suis venu à ceci:

// Windsor 2.x 
container.Register(
    AllTypes.FromAssemblyNamed("MyApp.ServicesImpl") 
    .Where(type => type.IsPublic) 
    .WithService.FirstInterface() 
    ); 

Cela passe par toutes les classes publiques dans l'assemblée MyApp.ServicesImpl.dll et enregistre chaque dans le conteneur en utilisant la première interface qu'il implémente. Parce que je veux toutes les classes dans l'ensemble des services, je n'ai pas besoin d'interface de marqueur.

Ce qui précède fonctionne pour une ancienne version de Windsor. L'actuel Castle Windsor documentation for registering components pour la dernière version suggère ce qui suit:

// Windsor latest 
container.Register(
    AllTypes.FromAssemblyNamed("MyApp.ServicesImpl") 
    .Where(type => type.IsPublic) // Filtering on public isn't really necessary (see comments) but you could put additional filtering here 
    .WithService.DefaultInterface() 
    ); 
+0

vous n'avez pas besoin de' Where (type => type .IsPublic) '. Windsor ne scannera les types exportés (ce qui signifie public ou niché public) que par défaut. –

+0

Je pensais cela, mais je pense que vous avez besoin de 'Where (quelque chose)' car la méthode 'WithService' n'est pas sur la valeur de retour de' FromAssemblyNamed() '. Oh, à moins que j'ai eu un #intellisensefail ... Je vais vérifier ... –

+0

Je viens de vérifier, il ne compile certainement pas pour moi. Étant donné que je suis actuellement sur une ancienne version de Windsor, je suppose que c'est à cela, et mettre à jour la réponse ci-dessus concernant Windsor plus tard. Merci beaucoup pour la contribution. :) –