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

如何基于接口创建泛型对象,实现DataRow到实体类的统一转换

解决方案

1. 泛化数据转换逻辑(核心修改)

将ApiConsumer改为泛型方法,通过泛型约束确保目标类型可实例化且实现数据转换接口,直接返回强类型列表,避免重复迭代逻辑:

[Route("api/GetClassA")]
[HttpPost]
public List<DerivedA> GetDerivedA()
{
    return ApiConsumer<DerivedA>("DerivedA");
}

[Route("api/GetClassB")]
[HttpPost]
public List<DerivedB> GetDerivedB()
{
    return ApiConsumer<DerivedB>("DerivedB");
}

// 泛型方法:约束T必须实现iObject接口,且有公共无参构造函数
public static List<T> ApiConsumer<T>(string apiName) where T : iObject, new()
{
    var dataTable = SomeDataTableAccessCaller(apiName);
    var returnList = new List<T>();

    // 遍历DataTable的行(原代码遗漏.Rows)
    foreach(DataRow row in dataTable.Rows)
    {
        // 直接创建派生类实例,而非接口
        T obj = new T();
        obj.DataTableConversion(row);
        returnList.Add(obj);
    }

    return returnList;
}

2. 修正实体类的序列化问题

原代码中实体字段为私有,JSON序列化无法读取,需改为公共属性;同时修正DerivedB的字段映射错误:

public class DerivedA : iObject
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void DataTableConversion(DataRow row)
    {
        Name = row["name"].ToString();
        Age = int.Parse(row["age"].ToString());
    }
}

public class DerivedB : iObject
{
    public string Name { get; set; }
    public string Address { get; set; }

    public void DataTableConversion(DataRow row)
    {
        Name = row["name"].ToString();
        // 原代码错误映射到age字段,修正为address
        Address = row["address"].ToString();
    }
}

public interface iObject
{
    void DataTableConversion(DataRow row);
}

3. 可选优化:用抽象基类封装通用逻辑

如果需要添加空值处理等通用转换逻辑,可将接口替换为抽象基类,减少派生类重复代码:

public abstract class BaseEntity
{
    // 通用安全转换方法,处理DBNull情况
    protected T SafeConvert<T>(object value)
    {
        if (value == DBNull.Value) return default;
        return (T)Convert.ChangeType(value, typeof(T));
    }

    // 抽象方法,强制派生类实现具体转换逻辑
    public abstract void DataTableConversion(DataRow row);
}

// 派生类继承抽象基类
public class DerivedA : BaseEntity
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override void DataTableConversion(DataRow row)
    {
        Name = SafeConvert<string>(row["name"]);
        Age = SafeConvert<int>(row["age"]);
    }
}

// 泛型方法约束同步修改
public static List<T> ApiConsumer<T>(string apiName) where T : BaseEntity, new()
{
    // 逻辑与之前一致
}

方案优势

  • 彻底复用迭代与实例化逻辑,避免重复代码
  • 保持强类型,直接返回API所需的派生类列表,无需类型转换
  • 解决接口无法实例化的核心问题
  • 修正原代码中的潜在错误(如DataTable遍历、字段映射)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:44:54