使用dart_eval执行字符串Dart代码时无法继承外部类的问题
解决dart_eval中字符串代码继承外部类的问题
要让eval字符串里的Dog继承外部定义的Animal,核心是通过dart_eval的桥接机制把外部类暴露给eval运行时——因为dart_eval的沙箱环境无法直接识别普通的外部Dart类。具体操作步骤如下:
1. 为Animal类创建桥接定义
定义一个桥接类作为外部Animal和eval沙箱的中间层,告诉编译器Animal的结构信息:
class $Animal extends $Instance { $Animal(Object? value) : super(value); static final $type = BridgeTypeRef(CoreTypes.object); static final $declaration = BridgeClassDef( BridgeClassType($type, isAbstract: false), // 注册无参构造函数,匹配外部Animal的构造方式 constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: $type, params: [])) }, methods: {}, getters: {}, setters: {}, fields: {}, ); @override $Value? getProperty(Runtime runtime, String identifier) { return super.getProperty(runtime, identifier); } @override void setProperty(Runtime runtime, String identifier, $Value value) { super.setProperty(runtime, identifier, value); } }
2. 注册桥接类到编译器和运行时
编译前把桥接定义传给编译器,运行时再绑定桥接类到真实的Animal类型:
// 编译阶段:让编译器识别Animal的桥接定义 final compiler = Compiler(); compiler.defineBridgeClasses([$Animal.$declaration]); // 运行阶段:绑定桥接类到真实的Animal构造函数 final runtime = Runtime.ofProgram(program) ..registerBridgeFunc('package:example/main.dart', 'Animal.', (runtime, target, args) => $Animal(Animal()));
完整修改后的代码
import 'package:dart_eval/dart_eval.dart'; import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:dart_eval/dart_eval_extensions.dart'; import 'package:dart_eval/stdlib/core.dart'; class Animal {} class $Animal extends $Instance { $Animal(Object? value) : super(value); static final $type = BridgeTypeRef(CoreTypes.object); static final $declaration = BridgeClassDef( BridgeClassType($type, isAbstract: false), constructors: { '': BridgeConstructorDef(BridgeFunctionDef(returns: $type, params: [])) }, methods: {}, getters: {}, setters: {}, fields: {}, ); @override $Value? getProperty(Runtime runtime, String identifier) { return super.getProperty(runtime, identifier); } @override void setProperty(Runtime runtime, String identifier, $Value value) { super.setProperty(runtime, identifier, value); } } void main(List<String> args) { final source = ''' class Dog extends Animal { } Dog test() { final dog = Dog(); return dog; } int sum(int a, int b) { return a + b; } int calculate() { test(); return sum(1, 1); } '''; final compiler = Compiler(); compiler.defineBridgeClasses([$Animal.$declaration]); final program = compiler.compile({'example': {'main.dart': source}}); final runtime = Runtime.ofProgram(program) ..registerBridgeFunc('package:example/main.dart', 'Animal.', (runtime, target, args) => $Animal(Animal())); final result = runtime.executeLib('package:example/main.dart', 'test', []); print(result); }
关键原理说明
- dart_eval的运行时是独立沙箱,外部类必须通过桥接机制才能被沙箱内代码访问、继承。
$Animal作为中间层,负责在外部Animal实例和eval沙箱的内部表示之间转换数据、传递调用。
内容的提问来源于stack exchange,提问作者ZhangWei-Bi
相关产品推荐
相关产品推荐

