泛型Sheet类设计问题:如何在Book中存储多类型数据Sheet
嘿,我完全懂你现在卡在哪了——泛型处理不同类型集合的时候确实容易钻进死胡同,不过其实有个很直白的解决办法,咱们一步步捋:
核心思路:用非泛型基类/接口统一存储不同的Sheet
问题的根源在于Sheet<T>是泛型类,直接用List<Sheet<T>>只能存同一种T类型的工作表。咱们可以先定义一个非泛型的通用接口/抽象类,让所有Sheet<T>都实现它,这样Book里就能用这个非泛型类型的列表来容纳各种不同的工作表了。
步骤1:定义非泛型的ISheet接口
先把所有Sheet都需要的通用属性/方法抽出来,做成一个不带泛型的接口:
public interface ISheet { // 工作表名称是所有Sheet都有的通用属性 string SheetName { get; set; } // 通用方法:初始化Excel列的逻辑 void PrepareExcelColumns(); }
步骤2:让泛型Sheet实现ISheet
现在你的Sheet<T>可以保留泛型特性,同时实现这个非泛型接口,这样它就具备了“通用Sheet”的身份:
public class Sheet<T> : ISheet { public string SheetName { get; set; } // 依然保留泛型的Data列表,存储特定类型的数据 public List<T> Data { get; set; } = new List<T>(); public void PrepareExcelColumns() { // 这里可以根据T的属性生成Excel表头,比如用反射获取T的公共属性名 var properties = typeof(T).GetProperties(); // 后续生成Excel时的表头逻辑可以在这里完成 } }
步骤3:改造Book类,用List存储工作表
现在Book里的Sheets列表就可以换成List<ISheet>,这样不管是Sheet<Dog>还是Sheet<Planet>,都能轻松加进去:
public class Book { public List<ISheet> Sheets { get; set; } = new List<ISheet>(); // 便捷方法:直接添加泛型Sheet public void AddSheet<T>(Sheet<T> sheet) { Sheets.Add(sheet); } // 生成Excel的核心方法 public void GenerateExcel(string outputPath) { foreach (var sheet in Sheets) { // 两种处理数据的方式可选: // 方式1:针对特定类型做定制化处理 if (sheet is Sheet<Dog> dogSheet) { foreach (var dog in dogSheet.Data) { // 写入dog.Name、dog.Age等字段到Excel } } else if (sheet is Sheet<Planet> planetSheet) { foreach (var planet in planetSheet.Data) { // 写入planet.Name、planet.Diameter等字段到Excel } } // 方式2:用反射通用处理所有类型(更灵活,不用加一堆if-else) var sheetType = sheet.GetType(); if (sheetType.IsGenericType && sheetType.GetGenericTypeDefinition() == typeof(Sheet<>)) { // 获取Sheet<T>里的Data列表 var dataProp = sheetType.GetProperty("Data"); var dataList = dataProp?.GetValue(sheet) as IEnumerable; if (dataList == null) continue; // 获取T的类型和它的所有公共属性 var itemType = sheetType.GetGenericArguments()[0]; var properties = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance); // 生成表头:遍历properties取属性名 // 生成行数据:遍历dataList,逐个对象取属性值写入单元格 } } // 最后执行保存Excel文件的逻辑 } }
用法示例
现在你从EF获取不同结果集后,就能轻松构建Book并生成Excel了:
// 从EF获取不同类型的数据 var dogs = await _dbContext.Dogs.ToListAsync(); var planets = await _dbContext.Planets.ToListAsync(); // 创建Book和对应的Sheet var book = new Book(); book.AddSheet(new Sheet<Dog> { SheetName = "狗狗列表", Data = dogs }); book.AddSheet(new Sheet<Planet> { SheetName = "行星列表", Data = planets }); // 生成Excel文件 book.GenerateExcel(@"C:\output.xlsx");
这样既解决了Book容纳不同类型Sheet的问题,又保留了泛型的类型安全特性,后续扩展其他类型的Sheet(比如Sheet<Cat>)也完全没问题~
内容的提问来源于stack exchange,提问作者Atron Seige
相关产品推荐
相关产品推荐

