Domanda

Sto cercando di strutturare il mio codice in modo tale da ridurre / evitare la duplicazione del codice e ho incontrato un problema interessante. Ogni volta che il mio codice richiama una stored procedure, ho bisogno di passare alcune variabili che sono comuni alla stored procedure: quali nome utente, dominio, ip_server e client_ip. Questi tutti provengono sia da HttpRequest oggetto o un oggetto System.Environment.

Dal momento che questi sono passati ad ogni stored procedure, il mio primo pensiero è stato quello di creare una classe di utilità che è un wrapper database e inizializzare e passare questi ogni volta, quindi non c'è bisogno di farlo nel mio codice. Il problema è però che di classe C # (all'interno della cartella App_Code) non vede HttpRequest oggetto. Naturalmente, potrei passare questo come un argomento per l'involucro, ma che sarebbe sconfiggere l'intero scopo di creare l'involucro. Mi sto perdendo qualcosa qui?

Mi rendo conto che non è un affare enorme tale da ripetere 4 righe di codice ogni volta che io chiamo una stored procedure, ma avrei preferito eliminare la duplicazione del codice nelle primissime fasi.

È stato utile?

Soluzione

Impostare il livello di dati di ereditare da una classe base che contiene 4 proprietà per quei valori. Rendere il costruttore pubblico richiede quei 4 proprietà.

Poi fare qualcosa di simile a livello di business -. Classe di base con quei 4 immobili a costruttore

Quindi l'interfaccia utente fa nuova BusObj (Request [ "username"], ...) .method ()

All'interno del livello dati si può avere un metodo che costruisce una matrice SqlParameter con quelle 4 proprietà, allora ogni metodo può aggiungere ulteriori parametri alla matrice.

Altri suggerimenti

Come regola generale indipendentemente dal linguaggio di programmazione, se si può socchiudere gli occhi e il codice è lo stesso si dovrebbe fare un / metodo / funzione messaggio fuori di esso e passare i parametri.

Un'altra cosa da guardare una volta che hai i metodi che prendono un gran numero di parametri (4 è una buona regola, ma è sicuramente una base caso per caso) è il momento di fare quel metodo di prendere un oggetto come parametro anziché singoli parametri. 99,99999999999999999999% del tempo un tale oggetto dovrebbe essere immutabili (nessuna variabile istanza scrivibile).

HttpContext.Current ha informazioni simili a quello che si trova in HTTP Request e più importante è disponibile all'interno App_Code.

Ecco un'idea strana si può o non può piacere: definire una classe 'profilo' e una funzione che espande il profilo nelle argomentazioni delle funzioni che assumono gli argomenti comuni

.
class P {
    readonly string name;
    readonly string domain;
    public P(string name, string domain) {
        this.name = name; this.domain = domain;
    }
    public void inject(Action<string, string> f) {
        f(p.arg1, p.arg2);
    }
    public T inject<T>(Func<string, string, T> f) {
        return f(p.arg1, p.arg2);
    }
}

Potrebbe funzionare meglio in VB.net dove si ha l'operatore AddressOf. Sarei davvero prudenti utilizzando questo tipo di cosa, perché si potrebbe facilmente danneggiare la leggibilità e l'incapsulamento.

Vorrei tenerlo il modo in cui lo avete ora. E 'più pulito, più semplice per estendere / modificare, e più facile da test di unità.

Come per l'utilizzo HttpContext invece come alcuni altri hanno suggerito, direi che si tratta di una cattiva idea. Una volta che si inizia a introdurre le dipendenze nel dominio su HttpContext, è molto difficile tirarla fuori. Che cosa succede se in seguito si voleva utilizzare il modulo senza un HttpContext? Che dire di unità di prova?

Prova System.Web.HttpContext.Current.Request per ottenere la richiesta corrente.

Si sono probabilmente diretti verso un pendio scivoloso. Il punto da DRY è quello di non ripetere la logica di business in diversi luoghi in cui un cambiamento nei requisiti crea la necessità di modificare il codice in più luoghi simili. Non necessariamente refactoring solo perché 4 linee sono le stesse se queste 4 righe dipendono dal contesto. Lei ha anche rotto l'incapsulamento facendo riferimento alla HttpRequest in che si sta utilizzando una variabile globale. Come consumatore di voi classe che avrei dovuto conoscere il dettaglio di implementazione che ho potuto solo chiamare da un'applicazione Web.

Detto questo, se si prende in considerazione che e ancora voglia di continuare, qui è un'altra opzione per informazioni di questo tipo. Creare un SecurityPrincipal personalizzato (Implementare IPrincipal) che contiene le proprietà necessari e allegarlo al thread. Riempire quando l'utente accede in e quindi è possibile accedervi ovunque durante la richiesta. Il chiamante avrebbe ancora bisogno di assicurarsi che questo è stato fatto, ma almeno non è specifica piattaforma.

In caso contrario, per il miglior incapsulamento, passare in una classe con le proprietà necessari al costruttore per ogni oggetto che ha bisogno di consumare tali proprietà.

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