如何在Dart中动态执行(如Eval)?

geo*_*ler 3 eval dynamic dart

自从开始使用Dart以来,我一直在寻找一种方法来执行Dart(Text)Source(同一个程序可能会动态生成)作为Code.喜欢臭名昭着的"eval()"功能.

最近我发现了一些暗示,Isolates之间的通信端口支持某种"Spawn",似乎它可以允许这种"技巧".在Ruby中,还可以动态加载模块作为语言功能,也许在Dart中有一些方法可以做到这一点?

任何线索或简单的例子将不胜感激.

提前致谢!

geo*_*ler 10

Ladislav Thon提供了这个答案(在Dart论坛上),

我相信说Dart永远不会有eval是非常安全的.但它将有其他更结构化的动态生成代码的方法(代码名称镜像构建器).但是现在没有类似的东西了.

产生隔离的方法有两种:spawnFunction,它从新隔离区中的现有代码运行现有函数,所以没有你想要的东西,以及spawnUri,它从给定的URI下载代码并在新的隔离区中运行它.这本质上是动态代码加载 - 但动态加载的代码与现有代码隔离.它运行在一个新的隔离区中,因此与它通信的唯一方法是通过消息传递(通过端口).

谢谢Ladislav ......


Iir*_*kka 7

您可以通过首先从中构造数据 URI,然后将其传递到Isolate.spawnUri.

import 'dart:isolate';

void main() async {
  final uri = Uri.dataFromString(
    '''
    void main() {
      print("Hellooooooo from the other side!");
    }
    ''',
    mimeType: 'application/dart',
  );
  await Isolate.spawnUri(uri, [], null);
}
Run Code Online (Sandbox Code Playgroud)

请注意,您只能在 JIT 模式下执行此操作,这意味着您可能从中受益的唯一地方是 Dart VM 命令行应用程序 / package:build 脚本。它在 Flutter 发布版本中不起作用。

要从中获取结果,您可以使用端口

import 'dart:isolate';

void main() async {
  final name = 'Eval Knievel';
  final uri = Uri.dataFromString(
    '''
    import "dart:isolate";

    void main(_, SendPort port) {
      port.send("Nice to meet you, $name!");
    }
    ''',
    mimeType: 'application/dart',
  );

  final port = ReceivePort();
  await Isolate.spawnUri(uri, [], port.sendPort);

  final String response = await port.first;    
  print(response);
}
Run Code Online (Sandbox Code Playgroud)

我在我的博客上写过它