0

I have an array of object like this

var items = new object[]
{
    new {name= "house",code=1,price= 30},
    new {name= "water",code=2,price= 323},
    new {name= "food",code=3,price= 45}
};

I want to add each of these value into data table rows (so 1 object - 1 row) through a method which has parameter is an array of object.

I try to do like the code below but it just add each of object in my items array into a table cells in excel file (I've already added headers into my data table)

public void Create(object[] items)
{
    // table headers are created before this line.......
    var table = new DataTable();
    table.Rows.Add(items);
}

So what I need to do, like how to loop through my array and get each of its value to assign to a row. Expected result in my file:

Name   Code   Price
===================
house   1      30
water   2      323
food    3      45

Thank you (and please comment if my question is not clear enough)

TranQ
  • 139
  • 1
  • 7
  • Maybe [this answer](http://stackoverflow.com/questions/4023462/how-do-i-automatically-display-all-properties-of-a-class-and-their-values-in-a-s/4023521#4023521) helps. – Oliver Jan 13 '17 at 07:55
  • You should really create your own class/struct for this purpose instead of using anonymous types. – Abion47 Jan 13 '17 at 07:59
  • When you create your _local_ variable `items` in the very first line, you can use `var items = new[] { new {name= "house",code=1,price= 30}, /* ... */ }` to have the array of anonymous objects strongly typed. But as soon as you pass to a method, such as `Create`, you cannot have strong typing because there is no name for an anonymous type, so you cannot mention it in the method signature. So consider @Abion47's comment in that case. – Jeppe Stig Nielsen Jan 13 '17 at 08:06
  • @Abion47 many .NET methods rely on anonymous types, and he would use reflection in the end to create a generic method capable of working with any datatype. Anonymous types have their place in the world where it makes sense. – Matteo Marciano - MSCP Jan 13 '17 at 08:07
  • @Abion47 yeah, but because the values adding to data table will be different depends on what i want to create in excel file. So it's kinda hard for me to just declare a common class for all cases :))) – TranQ Jan 13 '17 at 08:08
  • Then you really need to rethink your design and what it is you are ultimately trying to do. Using anonymous types is just as hard-coding as using a class, but they make the entire process more difficult and unwieldy, not to mention it being a total abuse of their use. – Abion47 Jan 13 '17 at 08:34
  • you cannot add bunch of items like `table.Rows.Add(items);` because as you said one row is one object – a-man Jan 13 '17 at 09:00
  • @Abion47 I'm thinking a better approach for this problem, cause I can see it's really complicated in dealing with generic/ anonymous types. Thanks for your advice anyway – TranQ Jan 13 '17 at 15:12

3 Answers3

3

You should do

public void Create<T>(T[] items)
{

    var table = new DataTable();
    var props = typeof(T).GetProperties();
    // Dynamically create headers
    foreach(var p in props)
    {
        if(!table.Columns.Contains(p.Name))
           table.Columns.Add(p.Name, p.ReturnType);
    }

    // Dynamically add values
    foreach(var o in items)
    {
        var row = table.NewRow();
        foreach(var p in props)
        {
           row[p.Name] = p.GetValue(o);
        }
        table.Rows.Add(row);
    }
}

to write a fully reusable method.

EDIT Improved dynamic creation of columns

  • look promising, i'll try it. Thanks – TranQ Jan 13 '17 at 08:13
  • @Abion47 It's not redundancy. I create columns, then rows. Look at the [Remarks](https://msdn.microsoft.com/en-us/library/system.data.datatable.rows(v=vs.110).aspx) section of MSDN. However, this might be improved as it may try to add already existing columns. – Matteo Marciano - MSCP Jan 13 '17 at 08:18
1

You could use reflection:

var table = new DataTable();
table.Columns.Add("name", typeof(string));
table.Columns.Add("code", typeof(int));
table.Columns.Add("price", typeof(double));

foreach(var obj in items) {
    var row = table.NewRow();
    row["name"] = obj.GetType().GetProperty("name").GetValue(obj, null);
    row["code"] = obj.GetType().GetProperty("code").GetValue(obj, null);
    row["price"] = obj.GetType().GetProperty("price").GetValue(obj, null);
    table.Rows.Add(row);
}
Nikhil Vartak
  • 5,002
  • 3
  • 26
  • 32
0

You need to add columns first.

var table = new DataTable();
table.Columns.Add("name");
table.Columns.Add("code");
table.Columns.Add("price");

foreach (var item in items)
{
  table.Rows.Add(item);
}
Moshe D
  • 768
  • 1
  • 4
  • 13