使用 MetaLinks 有条件地跳过方法
Conditionally skip a method with MetaLinks
假设我们有一些方法
MyClass>>#method: arg
Transcript crShow: 'executed'
因此,当您执行 MyClass new method: 1
时,成绩单将充满 "executed" 行。
现在,如果 arg
为 0,我想跳过此方法。我尝试安装一个 而不是 元链接,条件是:
link := MetaLink new
condition: [ :arguments |
arguments first = 0 ]
arguments: #(arguments);
control: #instead.
(MyClass >> #method:) ast link: link
但是该方法不再 运行,如果 arg 不为 0,我想 运行 它。
我也试过用这种方式在元对象中做条件:
link := MetaLink new
metaObject: [ :ast :arguments :receiver |
arguments first = 0
ifFalse: [
ast compiledMethod
valueWithReceiver: receiver
arguments: arguments ] ];
selector: #value:value:value:;
arguments: #(node arguments receiver);
control: #instead.
(MyClass >> #method:) ast link: link
但在这种情况下,你最终会陷入无限递归,因为元链接被一遍又一遍地调用,尽管我认为 ast compiledMethod
应该 return 一个编译方法而不是反射对应物
是的,看起来"instead hooks"总是执行原方法的"instead",即使link条件不成立,区别只是我们是否[=26] =] 取而代之 link 评估的价值或只是 nil.
也许应该改为 links。
作为您的用例的解决方案,您可以使用 link 之前的 return 如果条件成立,则接收者只是 return:
| ml |
ml := MetaLink new.
ml control: #before.
ml condition:[:args | args first = 0] arguments:#(arguments).
ml selector:#value:.
ml metaObject:[:context | context return].
ml arguments:{#context}.
(MyObject>>#method:) ast link:ml.
#context 是 thisContext 细化 (RFThisContextReification) 的关键
假设我们有一些方法
MyClass>>#method: arg
Transcript crShow: 'executed'
因此,当您执行 MyClass new method: 1
时,成绩单将充满 "executed" 行。
现在,如果 arg
为 0,我想跳过此方法。我尝试安装一个 而不是 元链接,条件是:
link := MetaLink new
condition: [ :arguments |
arguments first = 0 ]
arguments: #(arguments);
control: #instead.
(MyClass >> #method:) ast link: link
但是该方法不再 运行,如果 arg 不为 0,我想 运行 它。
我也试过用这种方式在元对象中做条件:
link := MetaLink new
metaObject: [ :ast :arguments :receiver |
arguments first = 0
ifFalse: [
ast compiledMethod
valueWithReceiver: receiver
arguments: arguments ] ];
selector: #value:value:value:;
arguments: #(node arguments receiver);
control: #instead.
(MyClass >> #method:) ast link: link
但在这种情况下,你最终会陷入无限递归,因为元链接被一遍又一遍地调用,尽管我认为 ast compiledMethod
应该 return 一个编译方法而不是反射对应物
是的,看起来"instead hooks"总是执行原方法的"instead",即使link条件不成立,区别只是我们是否[=26] =] 取而代之 link 评估的价值或只是 nil.
也许应该改为 links。
作为您的用例的解决方案,您可以使用 link 之前的 return 如果条件成立,则接收者只是 return:
| ml |
ml := MetaLink new.
ml control: #before.
ml condition:[:args | args first = 0] arguments:#(arguments).
ml selector:#value:.
ml metaObject:[:context | context return].
ml arguments:{#context}.
(MyObject>>#method:) ast link:ml.
#context 是 thisContext 细化 (RFThisContextReification) 的关键