2013-03-06 10 views
5

Ho alcune classi che servono solo a contenere i dati. Ad esempioMetaprograming in C#: metodo Automatic ToString

public class EntityAdresse : IEntityADRESSE 
{ 
    public string Name1 { get; set; } 
    public string Strasse { get; set; } 
    public string Plz { get; set; } 
    public string Ort { get; set; } 
    public string NatelD { get; set; } 
    public string Mail { get; set; } 
    public int Id_anrede { get; set; } 
    public string Telefon { get; set; } 
    public int Id_adr { get; set; } 
    public int Cis_adr { get; set; } 
} 

Questo rappresenta un indirizzo. Come ho detto, contiene solo dati. Nessun metodo (so che l'interfaccia non ha senso qui ...)

Ora ho bisogno di implementare ToString per tutte queste Entity-Classes e ce ne sono molte.

La mia domanda è: Esiste una funzionalità di metaprogrammazione in C# che genera automaticamente questi metodi di tostring? Non voglio scrivere il codice della piastra della caldaia per ogni di queste classi.

In alternativa, potrei anche scrivere uno script perl o python per generare il codice. Ma preferisco farlo in C# direttamente.

risposta

7

In genere, è necessario ottenere tutti i valori di proprietà della classe e combinarli in un'unica stringa. Questo può essere fatto utilizzando il seguente approccio:

public override string ToString() 
{ 
    PropertyDescriptorCollection coll = TypeDescriptor.GetProperties(this); 
    StringBuilder builder = new StringBuilder(); 
    foreach(PropertyDescriptor pd in coll) 
    { 
     builder.Append(string.Format("{0} : {1}", pd.Name , pd.GetValue(this).ToString())); 
    } 
    return builder.ToString(); 
} 
+0

Dovrà anche visualizzare il nome della proprietà. –

+0

aggiornato .... Ho aggiunto i nomi delle proprietà qui. – platon

+0

@platon È possibile aggiornare la risposta con un controllo "null" su "pd.GetValue (this)". In quel caso stavo ottenendo un NullPointer sul toString. – FrailWords

3

La funzione è denominata riflessione. Un esempio più semplice sarebbe:

public class EntityBase 
    { 
     public override string ToString() 
     { 
      StringBuilder sb = new StringBuilder(); 

      foreach (var property in this.GetType().GetProperties()) 
      { 
       sb.Append(property.GetValue(this, null)); 
      } 

      return sb.ToString(); 
     } 
    } 

    public class TheEntity : EntityBase 
    { 
     public string Foo { get; set; } 
     public string Bar { get; set; } 
    } 

Si prega di precisarlo per soddisfare le vostre esigenze.

Come potete vedere l'idea è di avere una singola implementazione in una classe base in modo che tutte le discendands ereditino automaticamente lo stesso comportamento.

+0

Questo non mi dà il nome delle proprietà, giusto? – Luke

+0

'sb.AppendFormat (" {0} {1} ", property.Name, property.GetValue (this, null));' –

+0

Buon lavoro ma ... non è possibile estendere più EntityBase in questo caso – boctulus

1

Non esiste una funzionalità integrata nella lingua per eseguire questa operazione automaticamente, ma è possibile scrivere una libreria per farlo utilizzando le funzioni Expression nel framework per generare una funzione per farlo.

si avrebbe una funzione come questa:

Func<T,string> GenerateToString<T>() 

E nella classe avete qualcosa di simile:

public class EntityAdresse : IEntityADRESSE 
{ 
    private static readonly Func<EntityAdresse,string> s_ToString=Generator.GenerateToString<EntityAdresse>(); 

    public string Name1 { get; set; } 
    public string Strasse { get; set; } 
    public string Plz { get; set; } 
    public string Ort { get; set; } 
    public string NatelD { get; set; } 
    public string Mail { get; set; } 
    public int Id_anrede { get; set; } 
    public string Telefon { get; set; } 
    public int Id_adr { get; set; } 
    public int Cis_adr { get; set; } 

    public override ToString() 
    { 
     return s_ToString(this); 
    } 
} 

La sfida sta scrivendo GenerateToString. Usando il framework e il riflesso Expression sarai in grado di creare un delegato efficiente come se avessi scritto il codice a mano.

È possibile utilizzare la riflessione su di essa, ma il colpo di prestazioni inizierà presto a essere un problema.

0

C'è una struttura open source StatePrinter per la generazione automatica di ToString. È molto configurabile quindi dovrebbe soddisfare le tue esigenze. Il codice di introspezione può essere trovato a Introspection

Problemi correlati