2012-11-27 15 views
6

Sto costruendo un lettore di file flat generico che assomiglia a questo.Posso in qualche modo riordinare questo (uso eccessivo?) Di farmaci generici?

public class GenericReader<TComposite, THeader, TData, TTrailer> 
    where TComposite : GenericComposite<THeader, TData, TTrailer>, new() 
    where THeader : new() 
    where TData : new() 
    where TTrailer : new() 
{ 
    public TComposite Read() 
    { 
     var composite = new TComposite(); 

     composite.Header = new THeader(); 
     composite.Data = new TData(); 
     composite.Trailer = new TTrailer(); 

     return composite; 
    }   
} 

Potrebbe essere consumato in questo modo.

var reader = new GenericReader<Composite<Header, Data, Trailer>, Header, Data, Trailer>(); 

var composite = reader.Read(); 
Console.WriteLine(composite.Data.SomeProperty); 

Console.ReadLine(); 

Ecco le classi utilizzate.

public class Composite<THeader, TData, TTrailer> : GenericComposite<THeader, TData, TTrailer> 
{ 

} 

public class GenericComposite<THeader, TData, TTrailer> 
{ 
    public THeader Header { get; set; } 

    public TData Data { get; set; } 

    public TTrailer Trailer { get; set; } 
} 

public class Header { 
    public string SomeProperty { get { return "SomeProperty"; } } 
} 

public class Data { 
    public string SomeProperty { get { return "SomeProperty"; } } 
} 

public class Trailer { 
    public string SomeProperty { get { return "SomeProperty"; } } 
} 

C'è un modo per rimuovere o incapsulare le informazioni di tipo generico in GenericReader? Sto cercando un paio di occhi in più per mostrarmi qualcosa di ciò che mi è mancato. Abbiamo già fatto qualcosa con le interfacce di restituzione, e facendo in modo che il consumatore faccia un cast, ma a mio avviso trasferisce la responsabilità nella posizione sbagliata, oltre a una piccola penalizzazione delle prestazioni.

Grazie.

Modifica: Non ho bisogno del TComposite, posso solo restituire GenericComposite. Come potrei mancarlo?

public class GenericReader<THeader, TData, TTrailer> 
    where THeader : new() 
    where TData : new() 
    where TTrailer : new() 
{ 
    public GenericComposite<THeader, TData, TTrailer> Read() 
    { 
     var composite = new GenericComposite<THeader, TData, TTrailer>(); 

     composite.Header = new THeader(); 
     composite.Data = new TData(); 
     composite.Trailer = new TTrailer(); 

     return composite; 
    }   
} 

public class GenericComposite<THeader, TData, TTrailer> 
{ 
    public THeader Header { get; set; } 

    public TData Data { get; set; } 

    public TTrailer Trailer { get; set; } 
} 
+2

È possibile controllare la [revisione del codice SE] (http://codereview.stackexchange.com/). È davvero più adatto per le attività di revisione come questa. – tmesser

+3

Penso che questa domanda sia adatta a SO; non è una revisione del codice tanto quanto una domanda sull'interdipendenza degli argomenti di tipo generico (e il discorso sul sistema dei caratteri è decisamente in tema in SO) e modi per semplificarlo. –

+0

Per me, il tuo GenericReader suona più come un fabbrica quindi un tipo generico, a meno che mi manchi qualcosa. Sembra che tu lo creerai solo per eliminarlo subito dopo. Quindi c'è una ragione per l'esistenza di GenericReader oltre a fornire un Composito? Non è possibile che il composito abbia un metodo statico per generare istanze di se stesso? – LightStriker

risposta

2

Non c'è modo per eliminare la necessità per le dichiarazioni di tipo sui vincoli generici che avete.

Tuttavia, il caso d'uso suggerisce che questo è il comportamento più comune:

var reader = new GenericReader<Composite<Header, Data, Trailer>, 
    Header, Data, Trailer>(); 

Se questo è il caso, in cui è possibile fare ipotesi circa la frequenza con cui vengono utilizzati alcuni modelli, è possibile ereditare una type (o set di tipi) dalle classi generiche con definizioni di tipo chiuso che possono essere utilizzate più facilmente.

Nel caso di cui sopra, è possibile fornire queste classi per la base, casi più comuni (in aggiunta alle definizioni generiche):

public class Composite : GenericComposite<Header, Data, Trailer> { } 

public class GenericReader : GenericReader< 
    Composite, Header, Data, Trailer> 
{ } 

che sarebbe poi essere utilizzato in questo modo:

var reader = new GenericReader(); 

var composite = reader.Read(); 

Console.WriteLine(composite.Data.SomeProperty); 

Console.ReadLine(); 

Avrai ancora i tipi con i parametri generici da utilizzare per casi altamente specializzati, ma per casi di uso comune (che puoi determinare tramite analisi/conoscenza del dominio), puoi determinare qual è il più comune e fornire classi con impostare i parametri del tipo per assistere.

+0

Questo è quello che sto facendo in questo momento. Dovrebbe averlo aggiunto alla domanda. Piuttosto una soluzione sensata, imo! – JefClaes

+0

@JefClaes Recentemente ho avuto una situazione in cui avevo tre parametri generici, e due era il caso d'uso regolare, e ho scoperto che fornire quelli ereditati con parametri di tipo predefiniti (quello che raccomandavo) era il migliore per me. Serendipito, forse. – casperOne

Problemi correlati