有条件地跳过MetaLinks的方法

时间:2016-10-23 07:20:56

标签: reflection pharo

想象一下,我们有一些方法

MyClass>>#method: arg

    Transcript crShow: 'executed'

因此,当你MyClass new method: 1时,成绩单中充满了"已执行" 行。

现在我想在arg为0时跳过此方法。我已尝试使用条件安装而不是 metalink:

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应该返回一个已编译的方法而不是反射对应的

,但我会一遍又一遍地调用metalink。

1 个答案:

答案 0 :(得分:1)

是的,看起来“反而挂钩”总是“替代”原始方法执行,即使链接条件不成立,差异只是我们是否返回相反链接评估的值或只是

也许这应该改为链接。

作为用例的解决方案,如果条件成立,您可以使用只返回接收者的before链接:

| 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)