The following is an extension method (documentation) and custom attribute (documentation) that will take an IEnumerable(Of T) and convert it to a DataTable.
Extension Method:
Custom AttributeCode:Imports System.Reflection Imports System.Runtime.CompilerServices Module DataTableExtensionModule <Extension()> Public Function ToDataTable(Of T)(items As IEnumerable(Of T)) As DataTable Dim dataTableConverted = New DataTable(GetType(T).Name) Dim enumerableProperties = GetType(T). GetProperties(BindingFlags.Public Or BindingFlags.Instance). Where(Function(prop) Dim dataTableIgnore = prop.GetCustomAttribute(Of DataTableIgnoreAttribute) Return dataTableIgnore Is Nothing OrElse Not dataTableIgnore.IgnoreColumn End Function). ToArray() For Each prop In enumerableProperties Dim propertyType = If(Nullable.GetUnderlyingType(prop.PropertyType), prop.PropertyType) dataTableConverted.Columns.Add(prop.Name, propertyType) Next For Each item In items Dim values = New Object(enumerableProperties.Length - 1) {} For i = 0 To enumerableProperties.Length - 1 values(i) = enumerableProperties(i).GetValue(item, Nothing) Next dataTableConverted.Rows.Add(values) Next Return dataTableConverted End Function End Module
UsageCode:Public Class DataTableIgnoreAttribute Inherits Attribute Public Property IgnoreColumn As Boolean Sub New() IgnoreColumn = True End Sub End Class
Fiddle: https://dotnetfiddle.net/c4HLt6Code:Public Module Module1 Public Sub Main() Dim users = { New UserViewModel() With { .Username = "dday9" } } Dim auditLogs = { New AuditLogViewModel() With {.User = users.First(), .Description = "Foo"}, New AuditLogViewModel() With {.Description = "Bar"} } Dim dt = auditLogs.ToDataTable() Console.WriteLine(dt.ToPrettyPrintedString()) End Sub End Module Public Class UserViewModel Public Property Username As String End Class Public Class AuditLogViewModel <DataTableIgnoreAttribute> Public Property User As UserViewModel Public ReadOnly Property Username As String Get If (User Is Nothing) Then Return String.Empty End If Return User.Username End Get End Property Public Property Description As String End Class




Reply With Quote