2013-10-22 75 views
3

有沒有什麼方法可以根據Dart中的環境標誌或目標平臺有條件地導入庫/代碼?我試圖根據目標平臺在dart:io的ZLibDecoder/ZLibEncoder類和zlib.js之間切換。Dart包的有條件導入/代碼

有一篇文章介紹瞭如何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)分析器。

+0

如果它們都以相同的方式實現所有內容,爲什麼不在提取類中實現它,然後讓ParserHtml和ParserServer擴展該類? – Nathanial

+0

我打算讓其他類直接訪問或實例化'Parser',我不知道如何讓它們不直接引用ParserHtml或ParserServer來處理它。不過,也許有一些我可以使用的工廠模式。 – ALW

+0

import parserhtml.dart,它定義了一個類Parser,它是真實的子類,並且具有html版本的工廠構造函數。對服務器版本也是這樣做的。然後代碼可以是相同的,除了它輸入的內容。 –

回答

2

您可以使用鏡像(反射)來解決此問題。酒吧包path正在使用反射來訪問瀏覽器中的獨立VM或dart:html上的dart:io

該源碼位於here。好的是,它們使用@MirrorsUsed,因此只有所需的類才包含在鏡像API中。在我看來,代碼記錄非常好,應該很容易爲您的代碼採用解決方案。

從獲取者_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 '.'; 
    } 
} 

正如您在評論中看到的那樣,此時僅適用於Dart虛擬機。問題解決後6490也應該在Dart2Js中工作。這可能意味着此解決方案目前不適用於您,但稍後將是解決方案。

問題6943也可能有幫助,但描述了另一個尚未實現的解決方案。

+0

這看起來似乎具有最佳的長期潛力,所以我將其標記爲答案。 – ALW