Grails: adding dynamic methods within a plugin
I'm developing a plugin that adds a getFlashHelper
method to each controller. This method should return an instance of a FlashHelper
class.
Howev开发者_如何学运维er, the constructor of the FlashHelper
class must be passed the instance of the controller on which the getFlashHelper
method was called.
Hopefully the following code will explain what I'm doing a bit better
def doWithDynamicMethods = {ctx ->
application.controllerClasses*.metaClass*.getFlashHelper = {
def controllerInstance = delegate
// Avoid creating a new FlashHelper each time the 'flashHelper' property is accessed
if (!controllerInstance.metaClass.hasProperty('flashHelperInstance')) {
controllerInstance.metaClass.flashHelperInstance = new FlashHelper(controller: controllerInstance)
}
// Return the FlashHelper instance. There may be a simpler way, but I tried
// controllerInstance.metaClass.getMetaProperty('flashHelperInstance')
// and it didn't work
return controllerInstance.metaClass.getMetaProperty('flashHelperInstance').getter.invoke(controllerInstance, [] as Object[])
}
}
The code appears to work, but I can't help feeling that there must be an easier way of doing this. That last line is particularly gruesome. Is there any way I can simplify this?
Thanks, Don
Since controllers are created per-request, I'd store the helper as a Request attribute:
for (c in grailsApplication.controllerClasses) {
c.clazz.metaClass.getFlashHelper = { ->
def controllerInstance = delegate
def request = controllerInstance.request
def helper = request['__flash_helper__']
if (!helper) {
helper = new FlashHelper(controller: controllerInstance)
request['__flash_helper__'] = helper
}
helper
}
}
精彩评论