2010-02-05 3 views
6

Sto avendo una scoreggia cerebrale cercando di rendere il seguente metodo più generico in modo tale che qualsiasi List<T> possa essere passato per il parametro columnValues. Ecco quello che ho:Come posso rendere questo metodo di estensione più generico?

public static DataRow NewRow(this DataTable dataTable, List<string> columnValues) 
{ 
    DataRow returnValue = dataTable.NewRow(); 

    while (columnValues.Count > returnValue.Table.Columns.Count) 
    { 
     returnValue.Table.Columns.Add(); 
    } 

    returnValue.ItemArray = columnValues.ToArray(); 
    return returnValue; 
} 

ho potuto cambiarlo in un List<object> e convertire l'elenco originale prima di passarlo al metodo, ma sono sicuro che ci sia una soluzione migliore :-)

Edit :

Il post di Frank mi ha fatto ripensare a questo. Nella maggior parte dei casi, tale origine List<T> sarebbe un List<object> poiché i valori delle colonne saranno probabilmente di tipi diversi.

Per il mio utilizzo iniziale uno List<string> aveva senso perché stavo creando un set di dati da un parsing CSV che è tutto il testo in quel punto.

risposta

4

Sei praticamente fuori di fortuna, perché l'Array Oggetto del DataRow è un array di oggetti, cioè, in ultima analisi, si può passa solo nella lista degli oggetti.

Se si inserisce un parametro generico nell'elenco, tutti gli elementi dell'elenco dovrebbero essere di quel tipo, il che è altamente improbabile che sia utile.

Detto questo, al fine di ottenere numerose colonne, tutti con diverse tipologie, si potrebbe modificare il metodo di estensione ad accettare un oggetto in cui si crea un'istanza di un tipo anonimo:

table.NewRow(new { A = "Hello", B = 1, C = DateTime.Now }) 

Con l'aiuto di convertire i valori di tipo anonimo a una stringa, dizionario oggetto by reflection or by a dynamic method dovrebbe essere una cosa abbastanza utile.

+0

Lol sei punto è eccellente e non l'avevo considerato. Per il mio uso iniziale una lista aveva senso perché stavo creando un set di dati da un parsing CSV che è tutto il testo in quel punto. Per la maggior parte degli altri usi questo non avrebbe senso dato che i valori delle colonne molto probabilmente saranno di tipo diverso. –

2

Che dire

IEnumerable<object> 

in connessione con

columnValues.Select(x => x.ToString()).ToArray(); 
5

perché non utilizzare params object[]:

public static DataRow NewRow(this DataTable dataTable, params object[] objects) 
{ 
    DataRow returnValue = dataTable.NewRow(); 

    while (objects.Length > returnValue.Table.Columns.Count) 
    { 
     returnValue.Table.Columns.Add(); 
    } 

    returnValue.ItemArray = objects; 
    return returnValue; 
} 

Poi si può chiamare in questo modo:

myDataTable.NewRow(1,2,"hello"); 
1

Cosa succede ad usare una chiusura per specificare come generare l'ItemArray in base al vostro tipo di ingresso

public static DataRow NewRow<T>(this DataTable dataTable, List<T> columnValues, Func<T, string> itemArrayCriteria) 
{ 
    DataRow returnValue = dataTable.NewRow(); 

    while (columnValues.Count > returnValue.Table.Columns.Count) 
    { 
     returnValue.Table.Columns.Add(); 
    } 

    returnValue.ItemArray = columnValues.Select(x => itemArrayCriteria(x)).ToArray(); 
    return returnValue; 
}