简体   繁体   English

Dart包的条件导入/代码

[英]Conditional imports / code for Dart packages

Is there any way to conditionally import libraries / code based on environment flags or target platforms in Dart? 有什么方法可以根据环境标志或Dart中的目标平台有条件地导入库/代码吗? I'm trying to switch out between dart:io 's ZLibDecoder / ZLibEncoder classes and zlib.js based on the target platform. 我试图在dart:io的ZLibDecoder / ZLibEncoder类和基于目标平台的zlib.js之间切换。

There is an article that describes how to create a unified interface , but I'm unable to visualize that technique not creating duplicate code and redundant tests to test that duplicate code. 有一篇文章描述了如何创建一个统一的界面 ,但是我无法形象化这种技术,即不创建重复的代码,也不进行冗余测试以测试该重复的代码。 game_loop employs this technique , but uses separate classes (GameLoopHtml and GameLoopIsolate) that don't seem to share anything. game_loop 采用了这种技术 ,但是使用了似乎不共享任何东西的单独类(GameLoopHtml和GameLoopIsolate)。

My code looks a bit like this: 我的代码看起来像这样:

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
  }
}

I'd like to avoid duplicating code by having two separate classes -- ParserHtml and ParserServer -- that implement everything identically except for _inflateBytes . 我想通过具有两个单独的类(ParserHtml和ParserServer)来避免代码重复,除了_inflateBytes之外, _inflateBytes都实现相同的所有_inflateBytes

EDIT: concrete example here: https://github.com/radicaled/citadel/blob/master/lib/tilemap/parser.dart . 编辑:此处的具体示例: https : //github.com/radicaled/citadel/blob/master/lib/tilemap/parser.dart It's a TMX (Tile Map XML) parser. 这是一个TMX(磁贴图XML)解析器。

You could use mirrors (reflection) to solve this problem. 您可以使用镜子(反射)解决此问题。 The pub package path is using reflection to access dart:io on the standalone VM or dart:html in the browser. pub包路径正在使用反射来访问独立VM上的dart:io或浏览器中的dart:html

The source is located here . 源位于此处 The good thing is, that they use @MirrorsUsed , so only the required classes are included for the mirrors api. 好消息是,它们使用@MirrorsUsed ,因此仅将所需的类包含在mirrors api中。 In my opinion the code is documented very good, it should be easy to adopt the solution for your code. 我认为该代码已被很好地记录下来,应该很容易为您的代码采用该解决方案。

Start at the getters _io and _html (stating at line 72), they show that you can load a library without that they are available on your type of the VM. 从吸气器_io_html (在第72行声明)开始,它们表明您可以加载库,而在您的VM类型上不可用。 Loading just returns false if the library it isn't available. 如果库不可用,则加载只会返回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')];

Later you can use mirrors to invoke methods or getters. 稍后,您可以使用镜像来调用方法或获取方法。 See the getter current (starting at line 86) for an example implementation. 有关示例实现,请参见吸气剂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 '.';
  }
}

As you see in the comments, this only works in the Dart VM at the moment. 正如您在评论中看到的那样,目前这仅适用于Dart VM。 After issue 6490 is solved, it should work in Dart2Js, too. 解决问题6490后,它也应在Dart2Js中工作。 This may means that this solution isn't applicable for you at the moment, but would be a solution later. 这可能意味着此解决方案暂时不适合您,但以后将成为解决方案。

The issue 6943 could also be helpful, but describes another solution that is not implemented yet. 问题6943可能也有帮助,但描述了另一个尚未实现的解决方案。

Conditional imports are possible based on the presence of dart:html or dart:io , see for example the import statements of resource_loader.dart in package:resource . 基于dart:htmldart:io的存在,有条件的导入是可能的,例如,参见package:resourceresource_loader.dart的import语句。

I'm not yet sure how to do an import conditional on being on the Flutter platform. 我尚不确定如何在Flutter平台上进行导入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM