如何基于接口创建泛型对象,实现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
相关产品推荐
相关产品推荐

