8
votes

Comment utiliser un conteneur di / ioc avec le liant modèle dans ASP.NET MVC 2+?

Disons que j'ai une entité utilisateur et je voudrais définir la propriété CréationTime de la création dans le constructeur vers DateTime.now. Mais étant un test de test unitaire, je ne veux pas accéder directement à DateTime.now directement, mais utilisez un iTimeProvider: xxx

J'utilise Ninject 2 dans mon application ASP.NET MVC 2.0. J'ai un usercontroller et deux créations de méthodes (une pour obtenir et une pour la poste). Celui pour obtenir est simple, mais celui de la poste n'est pas si simple et pas aussi de l'avant: P parce que j'ai besoin de gâcher le classeur de modèle pour le dire d'obtenir une référence d'une mise en œuvre de ITimeProvider afin de pouvoir construire une instance utilisateur. xxx

Je voudrais également pouvoir conserver toutes les caractéristiques du liant de modèle par défaut.

Toutes les chances de résoudre ce problème / Elegant / etc? : D


1 commentaires

Connexes: NIJECT SPÉCIFIQUE SPÉCIFIQUE Stackoverflow.com/Questtions/9186560/...


3 Réponses :


5
votes

Que diriez-vous au lieu d'utiliser un iTimeProvider Essayez ceci: xxx

et dans votre test d'unité: xxx < P> Je sais que ce n'est pas très élégant, mais au lieu de jouer avec le classeur de modèle, cela pourrait être une solution. Si cela ne se sent pas comme une bonne solution, vous pouvez implémenter un classeur de modèle personnalisé et remplacer le Createmodel Méthode où vous injecteriez les dépendances dans le constructeur du modèle.


2 commentaires

Oui, cela pourrait fonctionner. Une variante de la vôtre pourrait être un constructeur par défaut comme SO: Utilisateur (): Ceci (TimeProvider.Instance) {} J'espérais toujours un moyen simple d'injecter un [quelque chose] entre le clavier par défautModel et le cadre ASP.NET MVC 2 ..


Eh bien, puis remplacer le par défautModelbinder est l'itinéraire que vous devrez prendre.



1
votes

Une autre option consiste à créer une classe différente pour représenter les utilisateurs qui n'ont pas encore été persistés pour ne pas avoir de propriété de date de création du tout.

Même si créationDate est l'un des invariants d'utilisateur , il peut être nullable dans votre modèle de vue - et vous pouvez la définir plus loin en aval, dans votre contrôleur ou votre domaine. couche.

Après tout, cela n'a probablement pas d'importance, mais l'attribut de date de création représente vraiment le moment où vous construisez une instance utilisateur ou serait-il plus approprié pour qu'il représente le moment d'un utilisateur soumet leurs données?


0 commentaires

20
votes

Quelques observations:

Ne pas injecter des dépendances Juste pour les interroger dans le constructeur

Il n'y a aucune raison d'injecter un utilisateur à un utilisateur juste d'invoquer maintenant immédiatement. Il suffit d'injecter le temps de création directement à la place: xxx

une très bonne règle de base liée à DI est que constructeurs ne doit exécuter aucune logique .

N'utilisez pas DI avec modélishinders

Un modèle de modèle ASP.NET MVC est un endroit très médiocre pour faire di, en particulier parce que vous ne pouvez pas utiliser l'injection de constructeur. La seule option restante est le localisateur de service statique anti-motif .

Un modèle modèle traduit http get et post des informations sur un objet fortement dactylographié, mais conceptuellement ces types ne sont pas des objets de domaine, mais similaires à Objets de transfert de données .

Une solution bien meilleure pour ASP.NET MVC consiste à renoncer complètement à des modèles personnalisés et à la place explicitement Embrasser que ce que vous recevez de la connexion HTTP est pas votre objet de domaine complet .

Vous pouvez avoir une recherche simple ou mappeuse pour récupérer votre objet de domaine dans votre contrôleur : xxx

this.userepository est une dépendance injectée.


5 commentaires

"Une bien meilleure solution pour ASP.NET MVC est de renoncer complètement à des modèles personnalisés et d'embrasser explicitement que ce que vous recevez de la connexion HTTP n'est pas votre objet de domaine complet." Maintenant c'est une pensée intéressante. Et si nous avons plusieurs entités avec des propriétés communes telles que la date de création dans l'exemple ci-dessus et que nous voulions les définir tous dans un classeur pour toutes nos entités (nous avons toutes les entités héritant une classe d'entité de base et c'est là que le liant est attaché à) ? Dans ce cas, le dumping, les liants entraîneraient une duplication de code dans chaque création sur chaque contrôleur ??


Le point est que cela n'a pas d'importance. Vous ne recevez pas d'entité, vous recevez un message HTTP (ou obtenez). Embrasser le protocole. Il existe de nombreuses autres façons d'éviter la duplication de code.


Comme ASP.NET MVC 3 bénéficie d'un support pour ImodelbinderProvider, il montre qu'ils pensaient dans les bonnes lignes, je suis donc en désaccord avec vos commentaires et mais bien comprendre où vous venez. Une autre option pourrait être de créer un contrôleur de base qui gère la logique répétitive ...


Votre réponse s'applique-t-elle lorsque des interfaces sont impliquées? J'essayais de faire accepter mon contrôleur d'accepter un paramètre d'interface qui est implémenté dans l'adaptateur d'entreprise (couche d'adaptateur UI-à-domaine - qui vit dans l'assembly UI). Ensuite, afin d'obtenir le contrôleur d'accepter un message J'utiliserais un ModelBinder personnalisé pour "créer une instance de l'interface"


Au niveau du protocole, quelque chose de très concret est en cours d'affichage (une chaîne). Ce n'est même pas un objet, il ne s'agit donc certainement pas d'une interface. La modélisation en tant qu'interface peut difficilement être dit d'adopter le protocole.