Reputation: 571
Can the code below be improved by LINQ or lambda:
foreach (var item in listItem)
{
var dataRow = dataTable.NewRow();
foreach (var col in dataTableColumnNames)
{
var p = listType.GetProperty(col);
if (p != null)
{
dataRow[col] = p.GetValue(item, null);
}
}
dataTable.Rows.Add(dataRow);
}
There is nothing wrong though in the program but i wanted to have a feel of LINQ/lambda.
Upvotes: 1
Views: 2327
Reputation: 134811
As the way you have written, no. Used the right way, you can use some LINQ here, you just need to write your code to facilitate its use. Here, LINQ can be used to gather the data to be added to the table. Then use a loop to add them all.
// let's create the table and its columns
var dataTable = new DataTable("My Table");
dataTable.Columns
.AddRange(new[] { "Name", "Address" }
.Select(n => new DataColumn(n))
.ToArray());
// the items to be added
var items = new[]
{
new { Name = "Bob", Address = "Foo Street" },
new { Name = "Joe", Address = "Bar Road" },
new { Name = "Jon", Address = "Baz Avenue" },
};
var itemType = items.GetType().GetElementType();
var rowDatas =
items.Select(item =>
from col in dataTable.Columns.Cast<DataColumn>()
let prop = itemType.GetProperty(col.ColumnName)
select new
{
col.ColumnName,
Value = prop != null
? prop.GetValue(item, null)
: null,
});
foreach (var rowData in rowDatas)
{
var row = dataTable.NewRow();
foreach (var cell in rowData)
row[cell.ColumnName] = cell.Value;
}
However you can abuse it and take advantage of the side effects of adding rows to data tables using the Add()
method on the table's row collection. You generally shouldn't do this but it does make things more compact.
var itemType = items.GetType().GetElementType();
items.Select(item =>
dataTable.Rows.Add( // create and add a new row with the following values
dataTable.Columns
.Cast<DataColumn>()
.Select(col => itemType.GetProperty(col.ColumnName))
.Select(prop => prop != null ? prop.GetValue(item, null) : null)
.ToArray()
)
).ToList(); // "execute" this thing
Upvotes: 1
Reputation: 3419
I would get property infos before entering the loop. I assume that the listItem
is of type List<T>
.
var properties = dataTableColumnNames
.Select(listItemType.GetProperty)
.OfType<PropertyInfo>() // drop null values
.ToList();
listItems.ForEach(item => {
var dataRow = dataTable.NewRow();
properties.ForEach(property =>
dataRow[property.Name] = property.GetValue(item, null));
dataTable.Rows.Add(dataRow);
});
Upvotes: 0
Reputation: 4626
Since your snippet is invoking statements in both its loops (doing assignment in the inner loop and calling Rows.Add() in the outer), this isn't a very good scenario to use LINQ in.
If you still want to write this in a more 'functional' way, the best you can probably do is use a ForEach() extension method instead of the loops, but the code would still end up pretty much the same and would actually not really use LINQ at all.
Trying really hard to use LINQ here, you'd end up with something like this:
listItem
.Select(item =>
{
var dataRow = dataTable.NewRow();
dataTableColumnNames
.Select(col => listType.GetProperty(col))
.Where(p => p != null)
.ForEach(p => dataRow[p.Name] = p.GetValue(item, null));
return row;
})
.ForEach(row => dataTable.Rows.Add(row));
I'm using the property's p.Name
instead of col
here to make this simpler, but the general functionality should be the same. As other answers stated, this will not improve readability either.
Note that a ForEach() extension method is not included in plain vanilla LINQ and you'd have to write your own if you don't already have one.
Upvotes: 4
Reputation: 3761
I think you should also consider readability, expecially if your code is likely to change in the future. Your code will not improve much using lamba expressions and will be harder to understand.
Upvotes: 1