2009-01-31 12 views
4

Je construis un moteur de blog pour tester certains concepts tels que TDD et en utilisant l'inversion de contrôle ... J'ai trouvé une configuration où j'aurais une interface générique IBlogRepository pour que je puisse supporter à la fois SQL et XML.Comment utiliser IoC dans une configuration comme celle-ci? Y a-t-il une meilleure façon de tester cela?

public interface IBlogRepository : IRepository 
{ 
    Post GetPostById(Guid postId); 
    Post GetPostByFriendlyUrl(string friendlyUrl); 

    List<Post> GetPostsByAuthor(string userName);  
    List<Post> GetPostByTags(params string[] tags); 
    List<Author> Authors { get; } 

    void Delete(Post post); 
    void Delete(Comment comment); 
    void Save(Post post); 
    void Save(Comment comment); 
} 

Le problème est le référentiel XML a besoin différentes ressources que la base de données que l'on fait ... voici le constructeur:

public XmlBlogRepository(string dataPath, IFileReader fileReader, IDirectoryReader directoryReader, ILogger logger) 
    { 
     this.dataPath = dataPath; 
     this.fileReader = fileReader; 
     this.directoryReader = directoryReader; 
     this.Logger = logger; 
    } 

FileReader, directoryReader et dataPath ne sont pas nécessaires par le dépôt de Blog SQL . Ceci rend la question de l'inversion du contrôle pour charger IBlogRepository impossible et rend également très difficile l'utilisation générique car ils ont des cteurs complètement différents.

La raison pour laquelle je dois les transmettre est parce que si je viens d'utiliser File.Open/Directory.GetFiles, je ne serais pas en mesure de tester la classe sans avoir des fichiers XML sur le disque dur.

+0

quel outil utilisez-vous pour le tester? –

Répondre

7

Je ne comprends pas pourquoi le fait que vos deux implémentations différentes ont IBlogRepository les signatures de ctor rendent l'IoC "impossible"; au contraire, c'est un scénario courant dans IoC. La façon dont il est adressé est que votre framework IoC (et seulement votre framework IoC) est responsable de l'appel du ctor de l'implémentation IBlogRepository désirée. Ainsi, votre fichier de configuration IoC (ou toute autre approche de configuration que vous utilisez) sait quelle implémentation est utilisée (quelque chose doit, après tout), mais les utilisateurs du service IBlogRepository n'y accèdent que via son interface.

+0

C'est la bonne réponse. L'idée est de charger toutes vos implémentations concrètes dans la configuration de l'IoC puis de les sortir via des abstractions (interface) pour les consommer. Satisfaire les dépendances de SQL par rapport à XML devient maintenant un exercice de configuration à l'exécution – chadmyers

+0

Je suis d'accord ... il n'y a rien de mal à avoir différentes signatures de constructeur pour différentes implémentations. Vous avez juste besoin de vous assurer que votre conteneur sait comment créer les dépendances pour les deux. –

1

Je pense qu'un fournisseur répond à vos besoins en mettant en place un fournisseur vous envelopper les ressources dans ce

ici une belle link

+0

C'est essentiellement ce que j'ai fait, mais comme je voulais que la classe soit testable, je devais passer les ressources en interfaces pour que les objets mockés/faux puissent prendre le contrôle des ressources (lecteur de fichiers, lecteur de données, etc. – sontek

+0

Provider Le modèle est meilleur que rien, mais sinon un anti-pattern à la lumière de nombreuses et meilleures alternatives (à savoir IoC - voir la réponse d'Andrew Swan) – chadmyers