Wrapping Controller / ApiController per rimuovere i boilerplates

4

Puntiamo a ridurre il rumore del codice che sarebbe comune per tutti i controller come CRUD di base.

public interface IGenericController<T, Y> where T : BaseMaster
{
    IEnumerable<T> Get();

    T Get(Y code);

    HttpResponseMessage Post(T entity);

    T Put(T entity);

    T Delete(Y code);
}

questo sarebbe usato come

public class AuditController : GenericController<AuditRepository, int>

Potremmo anche usare l'approccio Composition over Inheritance qui per il riutilizzo del codice, tuttavia ci saranno ancora rumori del codice, quindi lo facciamo come una scelta.

Sono un po 'titubante nel fasciare le classi di base .net esistenti. Una cosa che potrei essere certa è che i metodi virtuali non sono più esposti per l'override.

Ci sarebbero ulteriori complicazioni in questo approccio?

    
posta jbalintac 08.12.2016 - 07:25
fonte

3 risposte

1

È abbastanza comune usare un BaseController personalizzato da cui ereditano gli altri controller piuttosto che il Controller. Non penso che ci sia alcun pericolo particolare qui.

Tuttavia! Devo convenire che non è una buona pratica. Il tuo approccio suggerisce che andrai fino in fondo a repository generici.

Ma ad un certo punto dovrai affrontare una diversa logica di business o inserire parametri tra i diversi controller.

Invece di seppellire quello condizionale nell'albero ereditario, è meglio metterlo in primo piano nel controller o nel livello di servizio. (hai un livello di servizio?)

In alternativa, se davvero stai esponendo un repository generico con metodi identici, puoi farlo in un singolo controller, analizzando il tipo fuori dal percorso

Quando dico un singolo controller intendo qualcosa come ...

[Route="/{resourceType}/{id}"]
object Get(string resourceType, string id)
{
    var repo = repoFactory.GetForType(resourceType);
    return repo.Get(id)
}

Questo singolo controller e azione è chiamato per tutti i tuoi link

    
risposta data 08.12.2016 - 09:33
fonte
1

Stai sbagliando. Il tuo approccio viola semplicemente il principio di segregazione dell'interfaccia che dice

No client should be forced to depend on methods it does not use

Immagina se ho un controller UsersController che non supporta il metodo IGenericController<T, Y>.Delete(Y code) (per qualsiasi motivo) ma desidera riutilizzare la maggior parte della logica in GenericController<T, Y> , dovresti sovrascriverlo e lanciare un NotSupportedException .

Invece dovresti probabilmente spostare tutta la tua logica aziendale in un livello separato (pensa UserService ) e mantieni i controller sottili .

    
risposta data 08.12.2016 - 08:30
fonte
0

Questa esigenza sorge spesso, quando un'applicazione Web diventa sempre più incentrata sul cliente, quindi non ha più bisogno di molta gestione sul lato server. Per questi casi, c'è una libreria in giro, che ti aiuta a definire i controller di default senza realmente avere bisogno di avere in giro ogni controller: link

    
risposta data 08.12.2016 - 10:43
fonte

Leggi altre domande sui tag