Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Dart中实现动态属性?_Dart - Fatal编程技术网

如何在Dart中实现动态属性?

如何在Dart中实现动态属性?,dart,Dart,我希望能够使用noSuchMethod()中的查找来支持具有映射的动态属性。但是,最新的更改使传入的属性引用名称不可用。我可以理解缩小场景要求我们使用符号而不是字符串作为名称,但这使得实现可序列化动态属性变得困难。有人对如何解决这个问题有好的想法吗 我不能使用字符串名,因为在调用minifier之间字符串名不是固定的。(这将彻底破坏序列化) 如果您只需要“动态属性”,那么在地图中使用符号作为键就足够了。如果还希望序列化该映射,则需要跟踪原始字符串名称并将其用于序列化。反序列化时,必须从这些字符

我希望能够使用noSuchMethod()中的查找来支持具有映射的动态属性。但是,最新的更改使传入的属性引用名称不可用。我可以理解缩小场景要求我们使用符号而不是字符串作为名称,但这使得实现可序列化动态属性变得困难。有人对如何解决这个问题有好的想法吗

  • 我不能使用字符串名,因为在调用minifier之间字符串名不是固定的。(这将彻底破坏序列化)
如果您只需要“动态属性”,那么在地图中使用符号作为键就足够了。如果还希望序列化该映射,则需要跟踪原始字符串名称并将其用于序列化。反序列化时,必须从这些字符串创建新符号


请注意,所有这些场景(以及基本上涉及新符号的所有内容)都需要编译器创建原始名称到缩小名称的映射,并将此映射放入程序中,这当然会使其更大。

您可以执行以下操作:

将'dart:json'导入为json;
main(){
var t=新事物();
打印(t.bob());
印刷品(t.jim());
打印(json.stringify(t));
}
阶级的东西{
Thingy(){
_map[const Symbol('bob')]=“blah”;
_地图[常数符号('jim')]=“oi”;
}
最终地图_地图=新地图();
noSuchMethod(调用调用){
返回_map[invocation.memberName];
}
toJson()=>{
'bob':_映射[const Symbol('bob')],
‘jim’:_map[const Symbol(‘jim’)]};
}
更新-动态示例:

将'dart:json'导入为json;
main(){
var t=新事物();
t、 加上('bob','blah');
t、 加上('jim',42岁);
打印(t.bob());
印刷品(t.jim());
打印(json.stringify(t));
}
阶级的东西{
最终地图_keys=新地图();
最终地图_值=新地图();
添加(字符串键、动态值){
_钥匙[新符号(钥匙)]=钥匙;
_值[新符号(键)]=值;
}
noSuchMethod(调用调用){
返回_值[invocation.memberName];
}
toJson(){
var map=newmap();
_keys.forEach((符号,名称)=>map[name]=\u值[symbol]);
返回图;
}
}

您可以使用

因此,动态类可以如下所示:

导入“dart:mirrors”;
甲级{
最终_属性=新映射();
noSuchMethod(调用调用){
if(invocation.isAccessor){
final realName=MirrorSystem.getName(invocation.memberName);
if(invocation.isSetter){
//对于setter,realname看起来像“prop=”,因此我们删除“=”
final name=realName.substring(0,realName.length-1);
_properties[name]=invocation.positionarguments.first;
返回;
}否则{
return_properties[realName];
}
}
返回super.noSuchMethod(调用);
}
}
main(){
最终a=新a();
a、 i=151;
打印(a.i);//打印151
a、 someMethod();//抛出
}

感谢@Alexandre Ardhuin的解决方案,我做了一些修改,使其可以运行

导入“dart:mirrors”;
类对象{
最终_属性=新映射();
对象();
object.from(映射初始值){
initial.entries.forEach((element)=>\u属性[element.key]=element.value);
}
noSuchMethod(调用调用){
if(invocation.isAccessor){
final realName=MirrorSystem.getName(invocation.memberName);
if(invocation.isSetter){
//对于setter,realname看起来像“prop=”,因此我们删除“=”
final name=realName.substring(0,realName.length-1);
_properties[name]=invocation.positionarguments.first;
返回;
}否则{
return_properties[realName];
}
}
返回super.noSuchMethod(调用);
}
@凌驾
字符串toString(){
返回_properties.toString();
}
}
main(){
//这里不能使用var或对象类型,因为分析会考虑
// https://dart.dev/tools/diagnostic-messages#undefined_setter
//未为类型“object”定义setter“i”
//所以这里需要动态!
动态a=object.from({'a':123,'b':234});
a、 i=151;
print(a);//print{a:123,b:234,i:151}
试一试{
a、 someMethod();//抛出NoSuchMethodError
}捕获(e){
印刷品(e);
}
}

是的,问题是如何访问原始字符串名称?noSuchMethod不会公开原始字符串,你从调用对象得到的只是符号。好吧,当你把东西放入映射时,你必须记录原始名称。编辑:哦,是的,公认的答案是正确的,有一个反向映射。我不记得了。我真正想要的是像Expando一样的东西。我希望能够用固定属性+运行时可以添加的附加属性来定义Thingy。我添加了一个动态示例-这就是你的意思吗?这样做的好处是您不必使用反射,这意味着它将更好地与dart2js配合使用。处理setter也应该很容易,而不是使用add-您可以使用上面Alexadres示例中的一些代码。Oops-如果没有mirror.GetName(),您显然无法处理setter。@GregLowe如何抑制“未找到方法”错误,例如?啊:同时,在Dart中,调用未明确声明的对象上的方法已成为一种趋势。实名格式是否相当稳定,还是每次出现新版本的Dart时,我都要担心更新代码?我真的不知道是否指定了格式,但在Dart中有对setter
v=
的引用。所以我想说,它几乎被定义了。请随意在邮件列表或其他SO问题中提问:)这段代码无法运行。我得到
没有为c定义setter'I'