【问题标题】:Conditionally skip a method with MetaLinks有条件地跳过带有 MetaLinks 的方法
【发布时间】:2016-10-23 07:20:55
【问题描述】:

假设我们有一些方法

MyClass>>#method: arg

    Transcript crShow: 'executed'

因此,当您执行MyClass new method: 1 时,成绩单中会充满“已执行” 行。

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

【问题讨论】:

    标签: reflection pharo


    【解决方案1】:

    是的,看起来“替代钩子”总是“替代”原始方法执行,即使链接条件不成立,区别只是我们返回替代链接评估的值还是只是

    也许应该为链接更改此设置。

    作为您的用例的解决方案,您可以使用在条件成立时仅返回接收者的前链接:

    | 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 refication (RFThisContextReification) 的关键

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-17
      相关资源
      最近更新 更多