You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用构造函数创建泛型T对象列表时抛出‘未找到System.RuntimeType构造函数’异常

嘿,这个需求我熟!咱们来一步步实现这个通用的列表转换方法,把DataTable的每一行都转成对应的模型对象~

核心思路

我们需要做的就是遍历DataTable的每一行,利用反射找到模型类中接收DataRow的构造函数,然后用该行数据实例化模型对象,最后把所有对象收集到List<T>里返回。为了让代码更健壮,我们还要加一些校验,确保目标类型确实有符合要求的构造函数。

基础版本代码

先写一个最直观的实现,逻辑清晰,适合快速验证:

public List<T> GenerateResultList<T>(DataTable dataTable) where T : class
{
    var resultList = new List<T>();
    if (dataTable == null || dataTable.Rows.Count == 0)
        return resultList;

    // 获取T类型中接收DataRow的构造函数
    var constructor = typeof(T).GetConstructor(new[] { typeof(DataRow) });
    if (constructor == null)
    {
        throw new InvalidOperationException($"类型 {typeof(T).Name} 必须包含一个接收单个DataRow参数的公共构造函数!");
    }

    // 遍历每一行,实例化对象并加入列表
    foreach (DataRow row in dataTable.Rows)
    {
        var modelInstance = (T)constructor.Invoke(new object[] { row });
        resultList.Add(modelInstance);
    }

    return resultList;
}
性能优化:缓存构造函数

如果这个方法会被频繁调用,每次反射获取构造函数会有点性能损耗。我们可以加个静态字典缓存已经获取过的构造函数,后续调用直接复用:

// 静态字典缓存构造函数,避免重复反射
private static readonly Dictionary<Type, ConstructorInfo> _constructorCache = new Dictionary<Type, ConstructorInfo>();

public List<T> GenerateResultList<T>(DataTable dataTable) where T : class
{
    var resultList = new List<T>();
    if (dataTable == null || dataTable.Rows.Count == 0)
        return resultList;

    Type targetType = typeof(T);
    // 先从缓存取,没有再反射获取
    if (!_constructorCache.TryGetValue(targetType, out var constructor))
    {
        constructor = targetType.GetConstructor(new[] { typeof(DataRow) });
        if (constructor == null)
        {
            throw new InvalidOperationException($"类型 {targetType.Name} 必须包含一个接收单个DataRow参数的公共构造函数!");
        }
        _constructorCache[targetType] = constructor;
    }

    foreach (DataRow row in dataTable.Rows)
    {
        var modelInstance = (T)constructor.Invoke(new object[] { row });
        resultList.Add(modelInstance);
    }

    return resultList;
}
使用示例

假设我们有一个用户模型类,构造函数接收DataRow并绑定字段:

public class UserModel
{
    public string Username { get; set; }
    public int Age { get; set; }
    public DateTime RegisterDate { get; set; }

    // 必须有这个接收DataRow的构造函数
    public UserModel(DataRow row)
    {
        // 注意处理DBNull的情况,避免转换出错
        Username = row["Username"] is DBNull ? string.Empty : row["Username"].ToString();
        Age = row["Age"] is DBNull ? 0 : Convert.ToInt32(row["Age"]);
        RegisterDate = row["RegisterDate"] is DBNull ? DateTime.MinValue : Convert.ToDateTime(row["RegisterDate"]);
    }
}

然后调用方法就很简单了:

// 假设这是你的数据源DataTable
DataTable userDataTable = GetUserDataTable(); 

// 转换为模型列表
List<UserModel> userList = GenerateResultList<UserModel>(userDataTable);
注意事项
  • 确保模型类的构造函数是公共的,否则GetConstructor会找不到(如果非要用非公共构造,可以在获取时加上BindingFlags.NonPublic | BindingFlags.Instance参数)
  • 模型构造函数里要处理DBNull的情况,避免转换异常
  • 如果传入的DataTable为空或没有行,方法会返回空的List<T>,符合常规预期

内容的提问来源于stack exchange,提问作者ricky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:51:42