2009-11-19 8 views
5

Groovy bietet einige wirklich gute Sprachfunktionen für den Umgang mit und die Implementierung von Java-Interfaces, aber ich halte mich irgendwie fest.Interface dynamisch in Groovy implementieren mit invokeMethod

Ich möchte eine Schnittstelle auf einer Groovy-Klasse dynamisch implementieren und alle Methodenaufrufe auf dieser Schnittstelle mit GroovyInterceptable.invokeMethod abfangen. Hier ist, was ich versuchte, so weit:

public interface TestInterface 
{ 
    public void doBla(); 
    public String hello(String world); 
} 


import groovy.lang.GroovyInterceptable; 

class GormInterfaceDispatcher implements GroovyInterceptable 
{ 
    def invokeMethod(String name, args) { 
     System.out.println ("Beginning $name with $args") 
     def metaMethod = metaClass.getMetaMethod(name, args) 
     def result = null 
     if(!metaMethod) 
     { 
      // Do something cool here with the method call 

     } 
     else 
      result = metaMethod.invoke(this, args) 
     System.out.println ("Completed $name") 
     return result 
    } 

    TestInterface getFromClosure() 
    { 
     // This works, but how do I get the method name from here? 
     // I find that even more elegant than using invokeMethod 
     return { Object[] args -> System.out.println "An unknown method called with $args" }.asType(TestInterface.class) 
    } 


    TestInterface getThisAsInterface() 
    { 
     // I'm using asType because I won't know the interfaces 
     // This returns null 
     return this.asType(TestInterface.class) 
    } 

    public static void main(String[] args) 
    { 
     def gid = new GormInterfaceDispatcher() 
     TestInterface ti = gid.getFromClosure() 
     assert ti != null 
     ti.doBla() // Works 
     TestInterface ti2 = gid.getThisAsInterface() 
     assert ti2 != null // Assertion failed 
     ti2.doBla() 
    } 
} 

Rückkehr der Verschluss funktioniert gut, aber ich konnte nicht einen Weg, um den Namen der Methode herauszufinden, es aufgerufen wird.

Der Versuch, einen Proxy für die this-Referenz selbst zu erstellen (so dass Methodenaufrufe invokeMethod aufrufen) gibt null zurück.

Antwort

9

Sie könnten die Karte Zwang Funktion von Groovy verwenden, um dynamisch eine Karte zu erstellen, die die jeweilige Schnittstelle darstellt:

TestInterface getMapAsInterface() { 
    def map = [:] 

    TestInterface.class.methods.each() { method -> 
    map."$method.name" = { Object[] args-> 
     println "Called method ${method.name} with ${args}" 
    } 
    }  

    return map.asType(TestInterface.class) 
} 
+0

Vielen Dank, funktioniert wie ein Charme und sieht sauber aus und ich kann immer noch auf alle Mitglieder Variablen und Methoden zugreifen. – Daff

+0

Wie es aussieht, funktioniert dies nicht für Schnittstellen mit überladenen Methoden. –

0

die Antwort von Christoph abzuschließen, wie diese page erwähnt, können Sie eine Schnittstelle mit implementieren ein Verschluss. Zum Beispiel:

def map = [doBla: { println 'Bla!'}, hello: {world -> "Hello $world".toString()}] as TestInterface 
map.hello 'Groovy' // returns 'Hello Groovy' 
Verwandte Themen