Flutter中如何判断一个Type变量是否继承自另一个Type变量
在Flutter中判断Type继承关系并复用父类Excel转换器
核心解决思路
由于Flutter禁用镜像包(mirror),无法直接通过反射判断Type的继承关系,我们可以利用Dart类型转换的安全性间接验证子类型关系,同时修改Excel转换器的查找逻辑,让子类自动复用父类的转换规则。
步骤1:实现通用类型子类型判断函数
在ExcelExporter中添加工具函数,用于判断一个类型是否是另一个类型的子类型或自身:
class ExcelExporter { // ... 其他代码 // 验证subtype是否是supertype的子类型或自身 static bool _isTypeSubtypeOf(Type subtype, Type supertype) { if (subtype == supertype) return true; try { // 利用类型转换安全性:若subtype是supertype的子类型,null可安全转换 supertype? _ = null as subtype?; return true; } catch (_) { return false; } } }
步骤2:修改转换器映射与查找逻辑
精简转换器映射(仅保留父类规则),并实现支持子类型匹配的转换器获取方法:
class ExcelExporter { static Map<Type, CellValue Function(dynamic)> cellValueConverterMap = { String: (value) => TextCellValue(value ?? ''), int: (value) => IntCellValue(value ?? 0), double: (value) => DoubleCellValue(value ?? 0), bool: (value) => TextCellValue((value ?? false) ? 'Ja' : 'Nej'), DateTime: (value) => TextCellValue(DateFormat('dd-MM-yyyy HH:mm:ss').format(value ?? DateTime.now())), // 仅保留父类转换器,子类自动复用 DisplayableObject: (value) => TextCellValue(value?.displayText ?? ''), Null: (value) => const TextCellValue(''), }; // 获取支持子类型匹配的转换器 static CellValue Function(dynamic)? getConverterForType(Type type) { for (final entry in cellValueConverterMap.entries) { if (_isTypeSubtypeOf(type, entry.key)) { return entry.value; } } return null; } static bool _isTypeSubtypeOf(Type subtype, Type supertype) { if (subtype == supertype) return true; try { supertype? _ = null as subtype?; return true; } catch (_) { return false; } } }
步骤3:更新导出调用逻辑
替换原有的containsKey判断,使用新的getConverterForType方法验证是否有可用转换器:
ExcelExporter.exportToExcel( fileName: 'some_file_name.xlsx', sheetName: 'some_sheet_name', data: _someData, headers: listOfMyColumnConfigurations .where((cc) => cc.isDisplayed && ExcelExporter.getConverterForType(cc.type) != null) .map((cc) => cc.columnName), startedCallBack: _showSnackBarGenerateExcelFileStarted, failedCallBack: _showSnackBarGenerateExcelFileError, completedCallBack: _showSnackBarGenerateExcelFileComplete, );
步骤4:数据转换时复用逻辑
在实际处理单元格值转换的代码中,同样使用getConverterForType获取转换器:
// 示例:处理每行数据的单元格转换 for (final row in _someData) { final excelRow = <CellValue>[]; for (final columnConfig in listOfMyColumnConfigurations.where((cc) => cc.isDisplayed)) { final converter = ExcelExporter.getConverterForType(columnConfig.type); if (converter != null) { final cellValue = converter(row[columnConfig.columnIndex]); excelRow.add(cellValue); } } // 将excelRow写入Excel工作表 }
效果验证
现在EditDeliverySiteDto、Project等DisplayableObject的子类会自动匹配父类的转换器,无需重复添加到映射表;同时基本类型的继承关系也能正确识别(比如int会匹配num的转换器,若你添加了对应规则)。
内容的提问来源于stack exchange,提问作者HansBakn
相关产品推荐
相关产品推荐

