Question

Le mot Let j'ai une entité utilisateur et je voudrais le mettre de propriété CreationTime dans le constructeur à DateTime.Now. Mais être un test unitaire adopteur Je ne veux pas DateTime.Now d'accès directement, mais utilise un ITimeProvider:

public class User {
    public User(ITimeProvider timeProvider) {
        // ...
        this.CreationTime = timeProvider.Now;
    }

    // .....
}

public interface ITimeProvider { 
    public DateTime Now { get; }
}

public class TimeProvider : ITimeProvider {
    public DateTime Now { get { return DateTime.Now; } }
}

J'utilise ninject 2 dans mon application ASP.NET MVC 2.0. J'ai un UserController et deux méthodes (une Créer pour GET et un pour POST). L'une pour GET est simple mais celui POST est pas droit et pas en avant: P parce que je dois jouer avec le liant modèle pour lui dire d'obtenir une référence d'une mise en œuvre de ITimeProvider afin de pouvoir construire une instance d'utilisateur.

public class UserController : Controller {

    [HttpGet]
    public ViewResult Create() {
         return View();
    }

    [HttpPost]
    public ActionResult Create(User user) {

         // ...

    }
}

Je voudrais également être en mesure de garder toutes les caractéristiques du modèle de liaison par défaut.

Toute chance de résoudre ce simple / élégant / etc? : D

Était-ce utile?

La solution

Que diriez-vous au lieu d'utiliser un ITimeProvider essayez ceci:

public class User 
{
    public Func<DateTime> DateTimeProvider = () => DateTime.Now;

    public User() 
    {
        this.CreationTime = DateTimeProvider();
    }
}

Et dans votre test unitaire:

var user = new User();
user.DateTimeProvider = () => new DateTime(2010, 5, 24);

Je sais que ce n'est pas très élégante mais au lieu de jouer avec le modèle liant cela pourrait être une solution. Si cela ne se sent pas comme une bonne solution, vous pouvez mettre en œuvre un modèle de liaison personnalisé et remplacer le

Autres conseils

Quelques observations:

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

Il n'y a aucune raison d'injecter un ITimeProvider dans un utilisateur juste pour appeler Now immédiatement. Il suffit d'injecter le temps de création directement au lieu:

public User(DateTime creationTime)
{
     this.CreationTime = creationTime;
}

Une très bonne règle de base en rapport avec DI est que les constructeurs doivent effectuer aucune logique .

Ne pas utiliser DI avec ModelBinders

Un ASP.NET MVC ModelBinder est un endroit vraiment pauvre pour faire DI, en particulier parce que vous ne pouvez pas utiliser l'injection Constructor. La seule option qui reste est le statique Locator Service anti-modèle.

A ModelBinder HTTP GET et translatées informations POST à ??un objet fortement typé, mais conceptuellement ces types ne sont pas des objets de domaine, mais similaire à Transfert de données des objets .

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

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

public ActionResult Create(UserPostModel userPost)
{
    User u = this.userRepository.Lookup(userPost);
    // ...
}

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

Une autre option est de créer une autre classe pour représenter les utilisateurs qui n'ont pas été persisté encore qui ne sont pas une propriété de la date de création du tout.

Même si CreationDate est l'un des invariants de User, il peut être annulable dans votre modèle de vue -. Et vous pouvez le mettre plus en aval, dans votre couche de contrôleur ou de domaine

Après tout, il n'a probablement pas, mais si l'attribut date de création représentent vraiment le moment où vous construire une instance utilisateur , ou serait-il plus approprié pour elle pour représenter le moment où un utilisateur soumet leurs données?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top