14

Je suis au début du développement d'un nouveau projet ASP.Net MVC et j'utilise ce projet pour entrer dans DI. Je suis sûr que je vais aller avec Structure Map, mais ce n'est pas ce que je demande. Ce que j'essaie de comprendre, c'est comment organiser au mieux ma solution. Est-ce que le projet de test unitaire et le modèle obtiennent un fichier de configuration pour mapper leurs dépendances ou y a-t-il une classe pour les gouverner tous?Quelle est la meilleure façon d'organiser une solution ASP.Net MVC à l'aide de l'injection de dépendances?

De plus, y a-t-il des pièges à éviter avant d'aller trop loin dans ce domaine?

Merci beaucoup, tous .....

Mise à jour Je dois ajouter que quand je dis « organiser la solution », je ne parle pas au nombre de fichiers/dossiers, etc., mais plutôt comment structurer les classes qui sont impliquées avec DI. En particulier, comment gérer le bootstrapper. Je peux voir où un phrasé pauvre de ma part pourrait causer de la confusion.

+1

Mon piège de débutant avec StructureMap était des exceptions d'autorisation de sécurité sous la confiance moyenne. Vous voudrez regarder dans un autre conteneur DI si votre application s'exécute dans des environnements de confiance moyenne. –

Répondre

2

Pour encourager un meilleur TDD. Avoir deux projets de test et/ou namespeaces X.Unit.Tests & X.Integrations.Tests. J'ai mon code DI dans mon projet principal dans un "répertoire d'espace de nommage" (/ Config) mais dans mes tests de code d'intégration, je pourrais simplement appeler ces registres ou remplacer si nécessaire dans mes appareils de base ou configurations.

E.g.

/Config/ServiceRegistry.cs /Config/RepositoryRegistry.cs /Config/Bootstrapper.cs

En global.asax j'appelle Bootstrapper.Init() et ce appellera x.AddRegistry (nouveau ServiceRegistry ()) etc.

Dans mes tests unitaires vous ne besoin d'utiliser les DI que dans vos tests d'intégration. Dans mes tests d'intégration, par ex. Si je suis en train de tester NHibernate dans la base de données, je peux initialiser SM avec RepositoryRegistry dans TestSetUp avec une méthode d'assistance juste en enveloppant GetInstance().

Je ne sépare pas les projets .Bootstraper et .Domain jusqu'à ce que je dois absolument ... Trois projets, X, X.UnitTests, X.Integration si vous avez besoin de plus de déplacer plus tard. Je suis venu d'un arrière-plan/l'application de l'entreprise d'avoir des dizaines de projets, il se sentait une première réduction mais pas maintenant, je vais frapper la croissance rapide et réorganiser la structure des solutions plus tard si nécessaire.

10

Si vous êtes le seul à travailler sur le projet, je ferais ce que vous est logique de premier. Rien n'est pire que de vous imposer un répertoire ou une structure de projet que vous trouvez non intuitif. La classe BaseController est-elle dans le dossier \ Core \ ou le dossier \ Controller \? Personnellement, je regarderais dans le contrôleur mais certaines personnes jurent qu'il devrait être dans \ Core \ ou \ Bases.

Le premier piège de débutant pense que vous pouvez organiser votre code dans le mauvais sens et, d'une certaine manière, cela reflète le succès du projet. J'ai vu des projets où 30 fichiers étaient dans un dossier et d'autres projets où il y avait 20 dossiers pour 30 fichiers.

Le deuxième piège newbie oublie que par rapport à d'autres langues, vous avez l'avantage de l'intellisense, des outils de navigation et du refactoring de Visual Studio. Vous avez également un compilateur qui rend le placement d'un fichier beaucoup moins douloureux. Si vous mettez quelque chose dans le "mauvais" endroit, c'est ok, vous pouvez toujours le trouver et le faire glisser là où il doit être. Je vais être honnête, je travaille sur un projet en ce moment et je ne suis même pas sûr où certaines classes résident dans ma structure de fichiers. Aller à Définition/Déclaration sont des raccourcis clavier que j'utilise beaucoup. Parce que c'est seulement moi qui travaille avec le code c'est bien. Si je devais ajouter un autre développeur sur le projet, je nettoierais probablement les choses.

Personnellement, j'ai tendance à placer des Interfaces avec leurs types d'implémentation dans le même dossier. IPaymentGateway est dans le même dossier que AuthorizeNetGateway et PaypalGateway. Si je ne peux pas afficher tous les fichiers de ce dossier en même temps dans la barre latérale de l'explorateur de solutions, je déplace tous les fichiers de passerelle dans un dossier \ Gateway \.

Avec l'injection de dépendances ajoutée au mélange, je vous conseille de ne vous intéresser qu'aux explosions d'espaces de noms. La pire chose que vous pouvez faire est d'encombrer vos amorçeurs et vos fichiers avec de longues déclarations et des alias.

ForRequestedType<Customer> 

est plus propre que

using KevDog.Models 
using Customer=KevDog.Models.Customer 

ou

ForRequestedType<KevDog.Models.Customer> 

Une autre façon d'éviter ce problème est d'être explicite lorsque vos choses de nommage: Client, CustomerViewModel, CustomerController, CustomerDataRow, CustomerView

Pour TDD, vous devez presque avoir deux amorçeurs à gérer vos types de béton. Vous ne voulez vraiment pas que vos tests unitaires utilisent AuthorizeNetGateway: IPaymentGateway, plutôt StubGateway: IPaymentGateway.

Maintenant, je suis aussi nouveau chez DI donc je tendance à faire des choses très simples et refléter les 101 tutoriels de niveau et de la documentation. Entrer dans une injection dynamique basée sur une configuration de construction ne devrait être utilisé que lorsqu'une situation spécifique l'exige et vous savez exactement pourquoi vous le faites.

Je garde généralement la structure par défaut pour les applications MVC ainsi. Il est simplement plus facile d'avoir votre code dans la même structure que 99% de tous les tutoriels et vidéos.

Espérons que cela aide.

+0

Merci jfar! Le commentaire sur TDD est vraiment le genre de choses que je voulais vous poser. Je pense que l'idée d'un bootstrappeur pour chaque projet est la voie à suivre. Un dans le projet d'essai unitaire et un dans le projet MVC – KevDog

0

Voici ma première tentative de résoudre le même problème pour moi-même, mais puisque c'est ma première tentative j'espère que les gens pourraient commenter ou critiquer autant que j'espère que cela pourrait servir comme une solution possible pour vous:

public VatManager() 
: this(new VatManagerRegistry()) { } 

public VatManager(Registry registry) 
: this(new Action<IInitializationExpression>(x => { x.AddRegistry(registry); })) 
    { 
    } 

public VatManager(Action<IInitializationExpression> action) 
    { 
    ObjectFactory.Initialize(action); 
    data = ObjectFactory.GetInstance<IVatManagerData>(); 
    } 

je constructeur trois surcharges - le constructeur par défaut parameterless a connaissance du Registre concret StructureMap qui doit être créé pour être utilisé dans un contexte de production.Les deux autres permettent à d'autres codes qui instancient cette classe de gestionnaires de fournir leurs propres registres ou actions StructureMap afin qu'ils puissent contrôler les injections de dépendance elles-mêmes, comme dans le cas d'un test automatisé fournissant des mocks au lieu d'instances concrètes dépendances. Je dois ajouter que cette solution n'est pas spécifique à un contexte ASP.NET MVC et ne tire aucune information de configuration des fichiers * .config.