抽象 - 如何为多个类型创建通用静态方法以在 Dart/Flutter 中流经?

Abstraction - How do I create a generic static method for several types to flow through in Dart/Flutter?

好的,我正在尝试减少我的应用程序的大量样板代码。现在我看到需要进行一些重构和认真的抽象。

我想为我的数据库代码抽象 CRUD 操作。现在我正在为每个对象创建一个单独的文件并复制代码。我觉得一定有更好的方法,但我不知道如何在使用泛型进行抽象时保持显式类型安全。

我目前正在为每个对象做这样的事情:
我非常确定您可以看到这会如何让某人发疯,我的应用程序中有 45 多个对象......而且很多都比这更复杂。

abstract class HouseDatabaseAPI {

  /// CREATE EVENT
  /// Create house for authorized user
  static Future<void> createHouse({required House newHouse}) async {
    Box<House> houseBox = await Hive.openBox<House>('house_box');
    await houseBox.put(newHouse);
  }

  /// READ EVENT
  /// Get house for authorized user
  static Future<House?> getHouse() async {
    Box<House> houseBox = await Hive.openBox<House>('house_box');
    House? house = houseBox.getAt(0);
    return house;
  }

  /// UPDATE EVENT
  /// Update house for authorized user
  static Future<void> updateHouse({House? updatedHouse}) async {
    Box<House> houseBox = await Hive.openBox<House>('house_box');
    await houseBox.putAt(0, updatedHouse!);
  }

  /// DELETE EVENT
  /// Delete house from the local machine
  static Future<void> deleteGroup() async {
    Box<House> houseBox = await Hive.openBox<House>('house_box');
    await houseBox.deleteAt(0);
  }
}

当然我希望它是严格类型的而不是动态的。 我希望能够做什么而不是大量的流量控制语句(粗略的伪代码):


enum DatabaseAction {
   create,
   read,
   update,
   delete,
}

abstract class DatabaseRoutingAPI {
   
   Future<T> globalDatabaseCreateAction({
      DatabaseAction databaseAction,
      Object object,
      String databaseName,
      }) async {
         Box<T> houseBox = await Hive.openBox<T>(databaseName);
         await houseBox.put(object);
   }      

   ...

}

我将从我的关于 Hive 数据处理的书签中为您导航到一个好的来源 -> here

在这里我将尝试回答您的问题:

abstract class Database {
  Box get box;
  T get<T>(String id);
  List<T> getAll<T>();
  Future<void> delete(String id);
  Future<void> deleteAll(List<String> keys);
  Future<void> addUpdate<T>(String id, T item);
}

class DatabaseImplementing implements Database {
  const DatabaseImplementing(this._box);
  
  final Box _box;
  
  @override
  Box get box => _box;

  @override
  T get<T>(String id) {
    try {
      final data = box.get(id);
      
      if (data == null) {
        throw Exception('$T not in the box.');
      }
      
      return data;
    } catch (_) {
      rethrow;
    }
  }

  @override
  List<T> getAll<T>() {
    try {
      final data = box.toMap().values;
      
      if (data.isEmpty) {
        throw Exception('$T not in the box.');
      }

      return data.toList().cast<T>();
    } catch (_) {
      rethrow;
    }
  }

  @override
  Future<void> delete(String id) async {
    try {
      await box.delete(id);
    } catch (_) {
      rethrow;
    }
  }

  @override
  Future<void> addUpdate<T>(String id, T item) async {
    try {
      await box.put(id, item);
    } catch (_) {
      rethrow;
    }
  }

  @override
  Future<void> deleteAll(List<String> keys) async {
    try {
      await box.deleteAll(keys);
    } catch (_) {
      rethrow;
    }
  }
}

当然还有很多其他方法可以做到这一点。