8

Dart を使い始めて以来、Dart (テキスト) ソース (同じプログラムが動的に生成されている可能性がある) をコードとして実行する方法を監視してきました。悪名高い「eval()」関数のように。

最近、アイソレート間の通信ポートがある種の「スポーン」をサポートし、この「トリック」を可能にしているように見えるいくつかのヒントを見つけました。Ruby では、言語機能として動的にモジュールをロードする可能性もあります。おそらく Dart でこれを行う方法はありますか?

手がかりや簡単な例をいただければ幸いです。

前もって感謝します!

4

4 に答える 4

13

Ladislav Thon が (Dart フォーラムで) この回答を提供しました。

Dart には決して eval がないと言っても過言ではありません。ただし、コードを動的に生成するための、より構造化された他の方法 (コード名はミラー ビルダー) を備えています。とはいえ、今はそんなことはありません。

アイソレートを生成するには 2 つの方法があります。spawnFunction は既存の関数を新しいアイソレートで既存のコードから実行するため、探しているものは何もありません。spawnUri は、指定された URI からコードをダウンロードして新しいアイソレートで実行します。これは基本的に動的コードの読み込みですが、動的に読み込まれたコードは既存のコードから分離されています。これは新しいアイソレートで実行されるため、通信する唯一の手段はメッセージ パッシング (ポート経由) を介することです。

ありがとうラディスラフ…

于 2012-11-27T13:24:14.937 に答える
1

Eval() は、少なくとも Ruby では、単一のステートメント (代入など) から関連するプログラムを完了するまで、何でも実行できます。多くの小さなスニペットを実行するには、可能な他のほとんどの実行形式よりもかなりの時間がかかります。

問題を詳しく見てみると、eval が使用される可能性のあるさまざまなスキームのベースにあった、少なくとも 3 つの異なる関数があります。Dart は、これらのうち少なくとも 2 つを最小限の方法で処理します。

Dart は、「一般的な」スクリプトの実行をサポートする予定はありません。

ただし、NoSuchMethod メソッドを使用すると、変数の動的な「注入」をローカル クラス環境に効果的に実装できます。eval() を次のような文字列に置き換えます: eval( "String text = 'your first name here';" );

Dart がすぐにサポートできるようになった 2 つ目の関数は、次のようなメソッドの呼び出しです。 eval( "Map map = SomeClass.some_method()" );

これをいじった後、最終的に、単一の単純なクラスを使用して、クラスのメソッドを呼び出すために必要な情報を、一般的なユーティリティがあると思われる文字列として格納できることに気付きました。一連のメソッドを呼び出すために必要になる可能性のある大きなメンテナンスの多い switch ステートメントを置き換えることができます。Ruby ではこれはほとんど些細なことでしたが、Dart では直感的とは言えない呼び出しがいくつかあるため、この「トリック」を 1 か所にまとめたいと思いました。

class.methodName() をキーだけで (文字列として) 呼び出すことができるように、リフレクションを使用して多くのクラス (ライブラリ全体?) をマップに「蓄積」するコードを次に示します。

注: Map & List 関数を実行するためにいくつかの「ヘルパー メソッド」を使用しました。おそらくそれらを単純な Dart に置き換えたいと思うでしょう。ただし、このコードは関数のみを使用して使用およびテストされています。

コードは次のとおりです。

//The used "Helpers" here..
MAP_add(var map, var key, var value){ if(key != null){map[key] = value;}return(map);}
Object MAP_fetch(var map, var key, [var dflt = null]) {var value = map[key];if (value==null) {value = dflt;}return( value );}


class ClassMethodMapper {
  Map    _helperMirrorsMap, _methodMap;

  void accum_class_map(Object myClass){
    InstanceMirror helperMirror = reflect(myClass);
    List methodsAr  = helperMirror.type.methods.values;
    String classNm  = myClass.toString().split("'")[1]; ///#FRAGILE      
    MAP_add(_helperMirrorsMap, classNm, helperMirror);
    methodsAr.forEach(( method) {
      String key = method.simpleName;
      if (key.charCodeAt(0) != 95) { //Ignore private methods
        MAP_add(_methodMap, "${classNm}.${key}()", method);
      }
    });
  }

  Map invoker( String methodNm ) {
    var method = MAP_fetch(_methodMap, methodNm, null);
    if (method != null) {         
      String classNm = methodNm.split('.')[0];        
      InstanceMirror helperMirror = MAP_fetch(_helperMirrorsMap, classNm);
      helperMirror.invoke(method.simpleName, []);
    }
  }

  ClassMethodMapper() {
    _methodMap         = {};
    _helperMirrorsMap  = {};
  }
}//END_OF_CLASS( ClassMethodMapper );


============

main() {
   ClassMethodMapper cMM = new ClassMethodMapper();
   cMM.accum_class_map(MyFirstExampleClass);
   cMM.accum_class_map(MySecondExampleClass);

   //Now you're ready to execute any method (not private as per a special line of code above)
   //by simply doing this:
   cMM.invoker( MyFirstExampleClass.my_example_method() );
}
于 2013-01-10T10:00:29.813 に答える