2010-01-28 52 views
0

我正在开发一个插件,为每个控制器添加getFlashHelper方法。该方法应该返回一个FlashHelper类的实例。Grails:在插件中添加动态方法

然而,FlashHelper类的构造必须通过在其上被调用的方法getFlashHelper控制器的实例

希望下面的代码会解释我在做什么好一点

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[]) 
    } 
} 

的代码似乎工作,但我不禁觉得必须有这样做的一个简单的方法。最后一行是特别可怕的。有什么办法可以简化吗?

谢谢, 唐

回答

1

由于控制器每个请求的创建,我会保存助手作为一个请求属性:

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 
    } 
} 
+0

如果我用这个方法我将最终造就了很多更多FlashHelper对象,即每个请求一个,而不是每个控制器类一个。请注意,在我使用的方法中,我在每个控制器类/ metaClass的FlashHelper上创建,而不是每个控制器实例都创建一个。 除了稍微更清晰的代码之外,这种方法还有什么优势吗? 谢谢! – 2010-01-28 04:17:14

+0

在标准的Spring MVC控制器中是单例,但是在Grails中为每个请求创建了一个新的控制器实例。所以我们都创建了相同数量的helper实例。将println或日志语句添加到getFlashHelper闭包中以进行验证。 – 2010-01-28 04:52:10

+0

但我的方法会为每个Controller **类**创建一个FlashHelper(每个控制器实例不是一个),而您的每个请求将创建一个。我仍然没有看到将FlashHelper存储为请求属性而不是metaClass属性的优点是什么? – 2010-01-28 15:49:06