Dart 包的条件导入/代码

Posted

技术标签:

【中文标题】Dart 包的条件导入/代码【英文标题】:Conditional imports / code for Dart packages 【发布时间】:2013-10-31 18:28:36 【问题描述】:

有没有什么方法可以根据 Dart 中的环境标志或目标平台有条件地导入库/代码?我正在尝试在 dart:io 的 ZLibDecoder / ZLibEncoder 类和基于目标平台的 zlib.js 之间切换。

有一篇文章描述了如何create a unified interface,但我无法想象这种技术不会创建重复代码和冗余测试来测试重复代码。 game_loopemploys this technique,但使用似乎不共享任何内容的单独类(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)解析器。

【问题讨论】:

如果它们实现的所有东西都相同,为什么不在提取类中实现它,然后让 ParserHtml 和 ParserServer 扩展该类? 我打算让其他类直接访问或实例化Parser,但我不确定在不让它们直接引用 ParserHtml 或 ParserServer 的情况下如何处理它。不过,也许我可以使用一些工厂模式。 import parserhtml.dart,它定义了一个 Parser 类,它是真正的 Parser 的子类,并具有 html 版本的工厂构造函数。对服务器版本执行同样的操作。那么除了导入的代码之外,代码可以是相同的。 【参考方案1】:

您可以使用镜像(反射)来解决这个问题。 pub 包 path 正在使用反射来访问独立 VM 上的 dart:io 或浏览器中的 dart:html

来源位于here。好消息是,他们使用@MirrorsUsed,因此只包含镜像 api 所需的类。在我看来,代码记录得很好,应该很容易为您的代码采用该解决方案。

从 getter _io_html(在第 72 行说明)开始,它们表明您可以加载库而不需要它们在您的 VM 类型上可用。如果库不可用,加载只会返回 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')];

稍后您可以使用镜像来调用方法或 getter。有关示例实现,请参见 getter 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 '.';
  

正如您在 cmets 中看到的,目前这只适用于 Dart VM。问题6490 解决后,它也应该在Dart2Js 中工作。这可能意味着此解决方案目前不适用于您,但稍后会成为解决方案。

问题6943 也可能有帮助,但描述了另一个尚未实施的解决方案。

【讨论】:

这似乎具有最佳的长期潜力,所以我将其标记为答案。【参考方案2】:

可以基于dart:htmldart:io 的存在进行条件导入,例如参见package:resource 中resource_loader.dart 的导入语句。

我还不确定如何在 Flutter 平台上进行导入。

【讨论】:

以上是关于Dart 包的条件导入/代码的主要内容,如果未能解决你的问题,请参考以下文章

Dart - 一个 dart 项目如何在不使用 pub 的情况下从另一个 dart 项目导入代码?

Flutter 条件导入移动端 vs 桌面端

Dart 错误:错误:当前 Dart 运行时不支持导入 dart:mirrors

颤振导入'package:flutter_svg/flutter_svg.dart';不适用于 VS 代码和 Android 工作室

如何导入依赖于 Flutter 平台的 Dart 文件或包?

Dart - 循环导入