In C #, come faccio a mantenere del tutto certe chiamate di metodo dal codebase?

Sto cercando di sbarazzarmi di tutte le chiamate di metodo DateTime.Now e di sostituirle con il mio metodo GetNow() , che a volte può restituire una data fissa a scopo di test.

Come posso far rispettare che nessuno aggiunge una chiamata DateTime.Now in futuro? Posso usare NDepend o StyleCop per controllarlo sul mio server di integrazione continua?

Con NDepend è molto facile scrivere questa regola :

 // Forbid DateTime.Now, use xxx.GetNow() instead WARN IF Count > 0 IN SELECT METHODS WHERE IsDirectlyUsing "OPTIONAL:System.DateTime.get_Now()" 

Avviso:

  • Il prefisso WARN IF Count> 0 IN che trasforma la query CQL in una regola
  • Il modo in cui la proprietà viene referenziata tramite la stringa System.DateTime.get_Now ()
  • Il prefisso OPZIONALE che significa “Non emettere un errore di compilazione se la proprietà get_Now non viene trovata”. Questo ha senso poiché se il tuo codice non usa più get_Now (), non viene più referenziato dall’analisi NDepend.

Inoltre, per generare la query originale …

 SELECT METHODS WHERE IsDirectlyUsing "OPTIONAL:System.DateTime.get_Now()" 

… fai semplicemente clic con il pulsante destro del mouse su DateTime.get_Now () e scegli Seleziona metodi … che vengono utilizzati direttamente da me

inserisci la descrizione dell'immagine qui

In primo luogo, DateTime.Now è una proprietà .
Ciò significa che non è necessario mettere parentesi dopo la chiamata.

In secondo luogo, se per scopi di test si intende un framework come NUnit, si potrebbe voler verificare Microsoft Moles che consente di sostituire qualsiasi chiamata di metodo statico con la propria implementazione personalizzata durante il test . Diamine, è fantastico:

 [Test] [ExpectedException (typeof (Y2KBugException))] public void TestY2KBug () { MDateTime.NowGet = () => new DateTime (2001, 1, 1); Bomb.DetonateIfY2K (); } public static class Bomb { public static void DetonateIfY2K () { if (DateTime.Now == new DateTime (2001, 1, 1)) throw new Y2KBugException (); // take cover! } } 

Non c’è un modo reale per far rispettare qualcosa di simile.

La cosa più vicina a cui verrai è la creazione di una regola FxCop personalizzata o di una regola personalizzata di analisi del codice di Visual Studio per l’errore / avviso sulle chiamate a DateTime.Ora.

È ansible utilizzare Moles nei test per fornire il proprio DateTime.Ora quando richiesto, senza la necessità di modificare alcun codice esistente che lo chiami.

Un’altra opzione potrebbe essere quella di modificare l’assembly dopo la compilazione per chiamare qualcos’altro. (Forse, usa Mono.Cecil per riscrivere l’IL, e aggiungi un comando al post-build in VS per eseguirlo.)

Potresti forse prendere la sorgente Mono e costruirti un mscorlib personalizzato con la funzione rimossa.

Un approccio potrebbe essere quello di aggiungere un hook pre-commit al repository di controllo del codice sorgente scelto per cercare DateTime.Now e interrompere il check-in se si trova la stringa incriminata. Non è infallibile e potrebbe essere noioso per i tuoi colleghi, ma dovrebbe aiutare a tenerlo fuori dal codice base.

Non penso che sia ansible. Quello che stai provando a fare è sovrascrivere la funzionalità della struttura di DateTime.

L’unico modo che posso pensare è solo quello di andare con una class personalizzata che avvolgerà funzionalità comuni di DateTime e offrire diverse funzionalità su richiesta …