缓存所有方法的结果

时间:2016-02-04 09:10:26

标签: caching reflection smalltalk pharo

我有一个类,它本质上是一些数据转换方法的集合。换句话说,我的文件中有一些数据,我使用一些不同的代码片段将文本数据转换为我可以轻松查询的内容。

现在这些方法经常重复使用,因为核心数据正在发生变化我想简单地缓存每个方法的结果,这是出于速度原因。

我不想通过添加:

来更改每种方法
^ methodsCache ifNil: [ methodsCache := "compute" ]

我想利用Pharo反射的力量来完成我的任务而不需要接触太多的代码。

我有一个想法是,如果我可以在每个方法之前运行一些代码,我可以返回缓存值或继续执行方法并缓存它的结果

3 个答案:

答案 0 :(得分:3)

您可以使用Reflectivity框架为您的方法添加前后链接。链接可以在透明执行之前检查缓存。

#cachedExecute:

此代码将安装一个元链接,使用参数MyClass#myMethodSelector发送到#control:对象。该链接安装在已编译方法的第一个AST节点上(同一方法选择器,但可以在另一个方法上)。 #myMethodSelector消息确保在执行AST节点之前执行链接。

您当然可以安装多个相互影响的元链接。

请注意,在上面的示例中,您必须再次在#cachedExecute:方法内发送相同的消息(#arguments:),因为您最终会进入循环。

<强>更新 上面的代码实际上有一个错误(现在已修复)。 #selector:消息采用一系列符号来定义通过#selector指定的方法的参数。这些参数将从上下文中具体化。要传递方法选择器,您可以使用#context具体化,方法上下文#arguments具体化和方法参数#key。要查看哪些可用的通知,请查看RFReification子类的类{{1}}。

答案 1 :(得分:0)

我的一个想法是定义

doesNotUnderstand: aMessage

    aMessage selector beginsWith: 'cached' ifFalse: [ ^ super doesNotUnderstand: aMessage ].

    ^ cache at: aMessage selector ifAbsentPut: [ 
        self perform: aMessage selector allButFirst: 6 ]

这样你唯一要做的就是用self methodName(或self cachedmethodName替换self cachedMethodName之类的所有邮件发送,但是你必须在{{1}中执行额外的小写变通方法}})

答案 2 :(得分:0)

另一个众所周知的选择是替换你的新的并返回一个缓存代理,委托给实际的对象