Условный импорт / код для пакетов 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).


person ALW    schedule 22.10.2013    source источник
comment
Если они оба реализуют все одинаково, почему бы вам не реализовать это в классе извлечения, а затем использовать ParserHtml и ParserServer для расширения этого класса?   -  person Nathanial    schedule 22.10.2013
comment
Я намереваюсь иметь другие классы, которые напрямую обращаются к Parser или создают экземпляры, и я не уверен, как я могу справиться с этим, не имея прямой ссылки на ParserHtml или ParserServer. Может быть, есть какой-то заводской шаблон, который я могу использовать для этого.   -  person ALW    schedule 23.10.2013
comment
import parserhtml.dart, который определяет класс Parser, который является подклассом реального и имеет фабричный конструктор для html-версии. Сделайте то же самое для серверной версии. Тогда код может быть таким же, за исключением того, что он импортирует.   -  person Alan Knight    schedule 23.10.2013


Ответы (2)


Вы можете использовать зеркала (отражение), чтобы решить эту проблему. Пакет pub path использует отражение для доступа 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 также может быть полезным, но описывает другое решение, которое еще не реализовано.

person Fox32    schedule 23.10.2013
comment
Кажется, что у него лучший долгосрочный потенциал, поэтому я отмечаю это как ответ. - person ALW; 24.10.2013

Условный импорт возможен в зависимости от наличия dart:html или dart:io, см., например, операторы импорта resource_loader.dart в package:resource.

Я еще не уверен, как сделать импорт при условии, что он находится на платформе Flutter.

person Hugo    schedule 07.11.2018