views:

171

answers:

4

I'm having a brain fart trying to make the following method more generic such that any List<T> can be passed in for the columnValues parameter. Here's what I have:

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;
}

I could change it to a List<object> and convert the original list prior to passing it to the method but I'm sure there is a better option :-)

Edit:

Frank's post made me rethink this. In most cases that source List<T> would be a List<object> since the column values will most likely be different types.

For my initial use a List<string> made sense because I was creating a dataset from a CSV parse which is all text at that point.

+1  A: 

What about

IEnumerable<object>

in connection with

columnValues.Select(x => x.ToString()).ToArray();
Dario
+3  A: 

You're basically out of luck, because the Item Array of the DataRow is an array of objects, that is, ultimately you can only pass in list of objects.

If you put in a generic parameter of the list all items of the list would have to be of that type, which is highly unlikely to be useful.

Having said that, in order to get numerous columns, all with different types, you could change your extension method to accept an object into which you instantiate an anonymous type:

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

With the aid to convert the anonymous type values to a string,object dictionary either by reflection or by a dynamic method it should be a fairly useful thing.

flq
Lol you're point is excellent and I hadn't considered it. For my initial use a List<string> made sense because I was creating a dataset from a CSV parse which is all text at that point. For most other uses this wouldn't make sense since the column values will most likely be different types.
Cory Charlton
+3  A: 

Why not just use 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;
}

Then you can just call it like this:

myDataTable.NewRow(1,2,"hello");
BFree
A: 

What about using a closure to specify how to generate the ItemArray based upon your input type

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;
}
Jon Erickson