Domanda

dire Let Ho un'entità utente e vorrei impostarlo della struttura CreationTime nel costruttore per DateTime.Now. Ma essendo una prova di unità adopter Io non voglio l'accesso DateTime.Now direttamente, ma uso 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; } }
}

Sto usando Ninject 2 nella mia applicazione ASP.NET MVC 2.0. Ho un UserController e due creano metodi (uno per GET e uno per il POST). Quello per GET è dritto in avanti, ma quello per POST non è così lineare e non così avanti: P perché ho bisogno di pasticciare con il modello legante di dire che per ottenere un riferimento di un'implementazione di ITimeProvider al fine di essere in grado di costruire un'istanza utente.

public class UserController : Controller {

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

    [HttpPost]
    public ActionResult Create(User user) {

         // ...

    }
}

Vorrei anche essere in grado di mantenere tutte le caratteristiche del legante modello predefinito.

Qualche possibilità per risolvere questo semplice / elegante / etc? : D

È stato utile?

Soluzione

Che ne dite invece di utilizzare un ITimeProvider provare questo:

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

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

E nella vostra unit test:

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

So che questo non è molto elegante ma invece di fare scherzi con il modello legante questa potrebbe essere una soluzione. Se questo non si sente come una buona soluzione è possibile implementare un modello personalizzato legante e ignorare il CreateModel metodo in cui si dovrebbe iniettare le dipendenze nel costruttore del modello.

Altri suggerimenti

Un paio di osservazioni:

Non iniettare le dipendenze solo di interrogare loro nel costruttore

Non c'è alcuna ragione per iniettare un ITimeProvider in un utente solo per richiamare immediatamente Now. Basta iniettare l'ora di creazione direttamente invece:

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

Una davvero buona regola relative al DI è che costruttori devono eseguire alcuna logica .

Non utilizzare DI con ModelBinders

Un ASP.NET MVC ModelBinder è un posto davvero povero di fare DI, in particolare perché non è possibile utilizzare Constructor iniezione. L'unica opzione che rimane è il statico Service Locator anti-modello .

Un ModelBinder traduce HTTP GET e POST informazioni a un oggetto fortemente tipizzato, ma concettualmente di questi tipi non sono gli oggetti del dominio, ma simile a Trasferimento dati Oggetti .

Una soluzione molto migliore per ASP.NET MVC è quello di rinunciare completamente e invece ModelBinders personalizzati esplicitamente abbracciare che quello che si riceve dalla connessione HTTP è non è il tuo oggetto di dominio completo .

Si può avere una ricerca semplice o mapper per recuperare l'oggetto del dominio nel controller:

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

dove this.userRepository è una dipendenza iniettato.

Un'altra opzione è quella di creare una classe diversa per rappresentare gli utenti che non sono stati ancora persisteva che non dispongono di una proprietà data di creazione a tutti.

Anche se CreationDate è una delle invarianti di User, può essere annullabile nel vostro modello di vista -. Ed è possibile impostare lo più a valle, nel vostro livello di controller o di dominio

Dopo tutto, probabilmente non importa, ma dovrebbe l'attributo data di creazione davvero rappresentare il momento in cui si costruire un'istanza utente , o sarebbe più appropriato per poter rappresentare il momento in cui un utente sottopone i loro dati?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top