2010-01-30 6 views
18

j'ai cette méthode WCFWCF injection de dépendance et de l'usine abstraite

Profile GetProfileInfo(string profileType, string profileName) 

et une règle métier:

si profileType est "A" lire la base de données.

si profileType est "B" lu à partir du fichier xml.

La question est: comment l'implémenter en utilisant un conteneur d'injection de dépendance?

Répondre

22

Voyons d'abord supposer que vous avez quelque chose d'IProfileRepository comme ceci:

public interface IProfileRepository 
{ 
    Profile GetProfile(string profileName); 
} 

ainsi que deux implémentations: DatabaseProfileRepository et XmlProfileRepository. Le problème est que vous souhaitez choisir le bon en fonction de la valeur de profileType.

Vous pouvez le faire en introduisant cette Abstract Factory:

public interface IProfileRepositoryFactory 
{ 
    IProfileRepository Create(string profileType); 
} 

En supposant que le IProfileRepositoryFactory a été injecté dans la mise en œuvre de service, vous pouvez maintenant mettre en œuvre la méthode GetProfileInfo comme ceci:

public Profile GetProfileInfo(string profileType, string profileName) 
{ 
    return this.factory.Create(profileType).GetProfile(profileName); 
} 

Une implémentation concrète de IProfileRepositoryFactory peut ressembler à ceci:

public class ProfileRepositoryFactory : IProfileRepositoryFactory 
{ 
    private readonly IProfileRepository aRepository; 
    private readonly IProfileRepository bRepository; 

    public ProfileRepositoryFactory(IProfileRepository aRepository, 
     IProfileRepository bRepository) 
    { 
     if(aRepository == null) 
     { 
      throw new ArgumentNullException("aRepository"); 
     } 
     if(bRepository == null) 
     { 
      throw new ArgumentNullException("bRepository"); 
     } 

     this.aRepository = aRepository; 
     this.bRepository = bRepository; 
    } 

    public IProfileRepository Create(string profileType) 
    { 
     if(profileType == "A") 
     { 
      return this.aRepository; 
     } 
     if(profileType == "B") 
     { 
      return this.bRepository; 
     } 

     // and so on... 
    } 
} 

Maintenant, vous avez juste besoin d'obtenir votre conteneur DI de choix pour câbler tout pour vous ...

+0

Ces 'ifs 'séquentiels pourraient être remplacés par un' switch/case' plus rapide/plus lisible. Et 'profileType' devrait vraiment être une énumération, pas une chaîne arbitraire. A part ça, c'est une excellente réponse. :) – Aaronaught

+3

Oui, pas de désaccord là-bas, mais je suis juste allé avec l'API donnée par l'OP :) –

+0

De quelle façon cela peut-il changer si je ne sais pas au moment de la compilation le nombre de dépôts? Et si mon wcf n'a que des dépendances avec la bibliothèque de logs et ces dépôts, où est le meilleur choix de conteneur DI? MEF est-il un bon choix dans ce scénario? – tartafe

4

Grande réponse par Mark, mais la solution donnée n'est pas usine abstraite mais la mise en œuvre de la norme Modèle d'usine. Veuillez vérifier comment les classes de marques s'inscrivent dans le diagramme UML de modèle d'usine standard. Puisque dans le modèle d'usine, l'usine est consciente des classes concrètes, nous pouvons rendre le code du ProfileRepositoryFactory beaucoup plus simple comme ci-dessous. Le problème avec l'injection des différents référentiels en usine est que vous avez plus de modifications de code chaque fois que vous ajoutez un nouveau type de béton. Avec le code ci-dessous vous suffit de mettre à jour le commutateur pour inclure nouvelle classe béton

 

    public class ProfileRepositoryFactory : IProfileRepositoryFactory 
    { 
     public IProfileRepository Create(string profileType) 
     { 
      switch(profileType) 
      { 
       case "A": 
        return new DatabaseProfileRepository(); 

       case "B": 
        return new XmlProfileRepository(); 
      } 
     } 
    } 
 

Abstract Factory est le modèle plus avancé utilisé pour la création de familles d'objets liés ou dépendants sans spécifier leurs classes concrètes. Le diagramme de classes UML disponible here l'explique bien.