Условный импорт / код для пакетов Dart
Есть ли способ условно импортировать библиотеки / код на основе флагов среды или целевых платформ в Dart? Я пытаюсь переключиться между dart:io
Классы ZLibDecoder / ZLibEncoder и zlib.js основаны на целевой платформе.
Есть статья, в которой описывается, как создать унифицированный интерфейс, но я не могу визуализировать этот метод, не создавая дублирующийся код и избыточные тесты для тестирования этого дублирующегося кода. game_loop
использует эту технику, но использует отдельные классы (GameLoopHtml и GameLoopIsolate), которые, похоже, ничего не делят.
Мой код выглядит примерно так:
class Parser {
Layer parse(String data) {
List<int> rawBytes = /* ... */;
/* stuff you don't care about */
return new Layer(_inflateBytes(rawBytes));
}
String _inflateBytes(List<int> bytes) {
// Uses ZLibEncoder on dartvm, zlib.js in browser
}
}
Я хотел бы избежать дублирования кода, имея два отдельных класса - ParserHtml и ParserServer - которые реализуют все идентично, за исключением _inflateBytes
,
РЕДАКТИРОВАТЬ: конкретный пример здесь: https://github.com/radicaled/citadel/blob/master/lib/tilemap/parser.dart. Это анализатор TMX (Tile Map XML).
2 ответа
Вы можете использовать зеркала (отражение), чтобы решить эту проблему. Путь пакета паба использует отражение для доступа dart:io
на автономной ВМ или dart:html
в браузере.
Источник находится здесь. Хорошо, что они используют @MirrorsUsed
, поэтому для зеркал api включены только необходимые классы. На мой взгляд, код задокументирован очень хорошо, должно быть легко принять решение для вашего кода.
Начните с добытчиков _io
а также _html
(указывается в строке 72), они показывают, что вы можете загрузить библиотеку без того, чтобы они были доступны на вашем типе виртуальной машины. Загрузка просто возвращает false, если библиотека недоступна.
/// If we're running in the server-side Dart VM, this will return a
/// [LibraryMirror] that gives access to the `dart:io` library.
///
/// If `dart:io` is not available, this returns null.
LibraryMirror get _io => currentMirrorSystem().libraries[Uri.parse('dart:io')];
// TODO(nweiz): when issue 6490 or 6943 are fixed, make this work under dart2js.
/// If we're running in Dartium, this will return a [LibraryMirror] that gives
/// access to the `dart:html` library.
///
/// If `dart:html` is not available, this returns null.
LibraryMirror get _html =>
currentMirrorSystem().libraries[Uri.parse('dart:html')];
Позже вы можете использовать зеркала для вызова методов или методов получения. Смотрите добытчик current
(начиная со строки 86) для примера реализации.
/// Gets the path to the current working directory.
///
/// In the browser, this means the current URL. When using dart2js, this
/// currently returns `.` due to technical constraints. In the future, it will
/// return the current URL.
String get current {
if (_io != null) {
return _io.classes[#Directory].getField(#current).reflectee.path;
} else if (_html != null) {
return _html.getField(#window).reflectee.location.href;
} else {
return '.';
}
}
Как вы видите в комментариях, на данный момент это работает только в Dart VM. После того, как проблема 6490 решена, она должна работать и в Dart2Js. Это может означать, что это решение не применимо для вас в данный момент, но будет решением позже.
Проблема 6943 также может быть полезной, но описывает другое решение, которое еще не реализовано.
Условный импорт возможен в зависимости от наличия dart:html
или же dart:io
см., например, операторы импорта resource_loader.dart в package: resource.
Я еще не уверен, как сделать импорт условным, будучи на платформе Flutter.