DataTable转List<Task>:能否无需指定字段自动推断属性实现简洁转换?
Convert DataTable to List Without Manual Field Mapping
Absolutely! You don’t need to manually map each column to your Task class properties—we can use reflection to auto-match column names to property names, or leverage a mature library like AutoMapper for even cleaner code. Let’s break down both approaches.
Prerequisite
First, make sure your Task class properties have names that match (or can be matched case-insensitively) with your DataTable’s column names. For example:
public class Task { public int TaskId { get; set; } // Matches a DataTable column named "TaskId" (or "taskid" if we ignore case) public string Description { get; set; } public DateTime? DueDate { get; set; } // Supports nullable types public bool IsCompleted { get; set; } }
Approach 1: Custom Reflection Extension Method (Lightweight)
This is a reusable, no-dependency solution that gives you full control over the mapping logic:
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; public static class DataTableExtensions { public static List<T> ToTypedList<T>(this DataTable dataTable) where T : new() { var resultList = new List<T>(); var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (DataRow row in dataTable.Rows) { var item = new T(); foreach (var prop in properties) { // Find matching column (case-insensitive check) var matchingColumn = dataTable.Columns.Cast<DataColumn>() .FirstOrDefault(col => string.Equals(col.ColumnName, prop.Name, StringComparison.OrdinalIgnoreCase)); if (matchingColumn != null && row[matchingColumn] != DBNull.Value) { // Handle nullable types (e.g., int?, DateTime?) var targetType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; var convertedValue = Convert.ChangeType(row[matchingColumn], targetType); prop.SetValue(item, convertedValue); } } resultList.Add(item); } return resultList; } }
How to Use It
// Assume you have your DataTable ready DataTable taskDataTable = FetchTaskDataFromDatabase(); // Convert in one line List<Task> taskList = taskDataTable.ToTypedList<Task>();
Approach 2: Use AutoMapper (For More Complex Scenarios)
If you’re already using AutoMapper in your project, it can handle this conversion with zero manual mapping code:
- Install AutoMapper via NuGet:
Install-Package AutoMapper - Configure the mapper (do this once, e.g., in your startup code):
var mapperConfig = new MapperConfiguration(cfg => { // AutoMapper automatically matches column names to property names cfg.CreateMap<DataRow, Task>(); }); IMapper mapper = mapperConfig.CreateMapper();
- Convert the DataTable:
List<Task> taskList = taskDataTable.AsEnumerable() .Select(row => mapper.Map<Task>(row)) .ToList();
Key Notes
- Case Insensitivity: Both solutions above handle case differences between column names and property names (e.g., "taskid" vs "TaskId").
- Nullable Types: The reflection method explicitly supports nullable value types, so you don’t have to worry about DBNull breaking conversions.
- Performance: Reflection is fast enough for most common scenarios. If you’re dealing with extremely large datasets, you might want to cache the property metadata to optimize repeated calls.
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

