如何在Dart中动态将泛型BaseModel转为实例以调用其方法?
动态创建Firestore泛型模型实例,替代手动Switch逻辑
我需要实现一个返回可查询Firestore集合引用的函数,基于抽象类BaseModel<R>。当前通过手动维护switch逻辑的convertTypesToObjects函数将泛型类型转为模型实例,再调用fromFirestore方法。希望改为直接通过泛型R创建实例(如var a = R())来调用fromFirestore,避免手动维护switch。
现有代码
基础模型
abstract class BaseModel<R> { String? createdAt; String? updatedAt; bool? isDisabled; bool? isDeleted; fromFirestore( DocumentSnapshot<JSON> snapshot, SnapshotOptions? options, ) {} toFirestore() {} toJson() {} }
集合引用转换函数
CollectionReference<R> collections<R extends BaseModel>( {required CollectionNames path}) { var ref = fireStore.collection(path.toPathStrings()); return ref.withConverter( fromFirestore: (snapshot, _) => convertTypesToObjects<R>().fromFirestore(snapshot, _), toFirestore: (model, _) => model.toFirestore(), ); }
手动类型转换函数
dynamic convertTypesToObjects<R>() { switch (R) { case ClinicModel: return ClinicModel(); default: throw AuthException(message: "Model Does not Exit"); } }
现有调用方式
await collections<ClinicModel>(path: CollectionNames.clinic);
期望实现
希望去掉switch逻辑,直接动态创建泛型实例:
var a = R(); return ref.withConverter( fromFirestore: (snapshot, _) => a.fromFirestore(snapshot, _), toFirestore: (model, _) => model.toFirestore(), );
解决方案
Dart中泛型类型无法直接实例化,需通过约束构造函数的方式实现:
1. 修改BaseModel抽象类
添加工厂构造函数,并明确方法返回类型:
abstract class BaseModel<R> { String? createdAt; String? updatedAt; bool? isDisabled; bool? isDeleted; // 定义工厂构造函数,强制子类实现无参构造 factory BaseModel() => throw UnimplementedError(); // 明确fromFirestore返回当前模型类型 R fromFirestore( DocumentSnapshot<JSON> snapshot, SnapshotOptions? options, ); // 明确toFirestore返回Map类型 Map<String, dynamic> toFirestore(); Map<String, dynamic> toJson(); }
2. 修改集合引用函数
更新泛型约束,允许创建R的实例:
CollectionReference<R> collections<R extends BaseModel<R>>({ required CollectionNames path, }) { final ref = fireStore.collection(path.toPathStrings()); return ref.withConverter( fromFirestore: (snapshot, _) { // 直接创建泛型实例并调用fromFirestore final model = R(); return model.fromFirestore(snapshot, _); }, toFirestore: (model, _) => model.toFirestore(), ); }
3. 子类实现要求
所有继承BaseModel的子类必须实现无参构造函数,例如ClinicModel:
class ClinicModel extends BaseModel<ClinicModel> { String? clinicName; // 必须实现无参构造 ClinicModel(); @override ClinicModel fromFirestore(DocumentSnapshot<JSON> snapshot, SnapshotOptions? options) { final data = snapshot.data(); createdAt = data?['createdAt']; updatedAt = data?['updatedAt']; isDisabled = data?['isDisabled']; isDeleted = data?['isDeleted']; clinicName = data?['clinicName']; return this; } @override Map<String, dynamic> toFirestore() { return { 'createdAt': createdAt, 'updatedAt': updatedAt, 'isDisabled': isDisabled, 'isDeleted': isDeleted, 'clinicName': clinicName, }; } @override Map<String, dynamic> toJson() => toFirestore(); }
这样修改后,无需再维护convertTypesToObjects函数,直接通过泛型动态创建实例即可。
内容的提问来源于stack exchange,提问作者James George
相关产品推荐
相关产品推荐

