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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:46:37