如何使用到两个具有相同类名的反序列化技术



在我的项目中,我试图同时使用基于Json的反序列化和基于flatbuffer的去序列化。例如,可以使用freezed包将来自后端api的Json反序列化为名为ModelInfo的类。假设该类在freezed_model.dart中定义

{
"model_name":"Model A",
"model_size": 50
}

现在,从同一个后端,我想使用flatbuffer序列化将这些信息作为字节数组发送。使用flatc,我可以生成代码,将其反序列化为具有相同信息的具有相同名称ModelInfo的另一个类。假设该类在flatbuffer_model.dart中可用

我想在flutter项目中跨UI层、管理器层或api层使用这些类,而不冲突imports。例如,如果我的小部件使用ModelInfo类,我希望它在编译和运行时从freezed_model.dartflatbuffer_model.dart动态解析。也许这是不可能的,但我相信约出去不会有什么坏处。

我尝试了有条件导入和有条件导出,但dart分析器对此不满意,我确信我的方法是错误的。

例如,我如下定义了一个名为CCD_ 11的类。

import 'package:scandal_view/src/config_reader.dart';
enum Environment { PROD, DEV }
class CurrentEnvironment {
static Environment _environment;
/// assigning a default _decodeMode thinking dart analyser be able to resolve classes during 
///conditional export or import.
static String _decodeMode = 'flatbuffers';
static void initialize(Environment environment) {
_environment = environment;
// reassigns the _decomeMode during runTime.
_decodeMode = ConfigReader.getDecodemode();
}
static Environment get environment => _environment;
static String get decodeMode => _decodeMode;
}

之后,在我的api类中,我尝试进行以下条件导入,但它不起作用。

import 'dummy_model.dart' 
if(CurrentEnvironment.decodeMode == 'json') 
'package:mypackage/lib/model/json/freezed_model.dart'
if(CurrentEnvironment.decodeMode == 'flatbuffer') 
'package:mypackage/lib/model/flatbuffers/flatbuffer_model.dart'

到目前为止,我的dummy_model.dart是空的。早些时候,我用它来导出上面提到的相同文件,但它没有帮助。我正在考虑使用facade模式来实现这一点,但这会导致太多的手工编写代码,并且容易出错,因为反序列化程序是自动生成的并且是安全的。

如果我不理解坏的情况,那么您试图实现的是将ModelInfo类与您选择的串行化/去串行化方法(无论是json、平面缓冲区等(解耦,对吧?

如果是这样的话,你提出的有条件进口将不起作用(如果真的起作用,我认为在维护、测试或扩展时这不是一个好的选择。

我的建议是以最简单的方式遵循某种Repository模式。这将使你能够真正解耦如何从消费者那里获得数据,这将允许你选择串行化/去串行化策略,甚至拥有多个串行化器等。如果你需要的话,这种方法还将使你在未来的应用程序中添加持久性/缓存变得非常容易。

让我们想象一个简单的场景,在这个场景中,您希望获取业务层(查看模型、bloc等(要使用的ModelInfo对象的列表,然后再获取UI。

首先假设我们有一个ModelInfo类,它是目标类(我们想从服务层发送到应用程序的上层(。

class ModelInfo {
// This is the model we want to expose to our upper layers (View Models, Blocs etc) 
}

1( 首先,我们将创建一个接口来定义每个ApiDataManager将实现的合同。在Dart中,我们使用抽象类:

abstract class ApiDataManager {
List<ModelInfo> fetchItems();
}

2-现在我们可以创建任意数量的Api数据管理器(json、flatbuffers等(,只要它们符合ApiDataManager。在这些管理器上,我们可以导入所需的库,并进行相应的api调用、解析等。只要我们有一个返回List<ModelInfo>fetchItems()方法,我们就可以了。

class jsonApi implements ApiDataManager {
List<ModelInfo> fetchItems() {
/* Here you implement a fetchItem method that parses your json server response
*  and returns an ItemModel list */
}
}
class flatBuffersApi implements ApiDataManager {
List<ModelInfo> fetchItems() {
/* Here you implement a fetchItem method that parses your flatbuffers server response
*  and returns an ItemModel list */
}
}

3-现在我们创建了一个存储库,我们将在其中注入您想要使用的远程API数据提供程序(json,flatbrasters(。这个存储库将由我们的视图模型、Blob等使用,以获取数据并获取成熟的模型对象。

class Repository {
final ApiDataManager remoteDataManager;
Repository(this.remoteDataManager);

List<ModelInfo> fetchItems() {
// Call remoteDataManager.fetchItems()
// Depending on the remote data manager you have injected you'll be 
// using json endpoints or flatbuffers, or whatever you want!
// Return the list to your view models, Blocs etc
return remoteDataManager.fetchItems();
}
}

4-最后,我们可以从我们的业务或表示层(我们的Widget(使用我们的Repository,并获得ModelInfo对象的列表。实际上,我们可以在运行时根据您想要使用的逻辑动态注入我们想要的Api类型。你可以在你的ViewModel、block或Widget中使用这样的逻辑:

// Imagine this is inside your Widget or View Model or bloc
bool isProd = false; // Whatever you want to use to control the logic
var myJsonApi = JsonApi();
var myFlatBuffersApi = FlatBuffersApi();
var apiToUse = isProd ? JsonApi() : FlatBuffersApi();
Repository myRepository = Repository(apiToUse);
// Here you have your fresh list of items!
List<ModelInfo> myItems =  myRepository.fetchItems();

我希望这能有所帮助!

最新更新