tags:

views:

1212

answers:

3

I know in Groovy you can invoke a method on a class/object using a string. For example:

Foo."get"(1)
  /* or */
String meth = "get"
Foo."$meth"(1)

Is there a way to do this with the class? I have the name of the class as a string and would like to be able to dynamically invoke that class. For example, looking to do something like:

String clazz = "Foo"
"$clazz".get(1)

I think I'm missing something really obvious, just am not able to figure it out.

Thanks.

+1  A: 

Try this:

def cl = Class.forName("org.package.Foo")
cl.get(1)

A little bit longer but should work.

If you want to create "switch"-like code for static methods, I suggest to instantiate the classes (even if they have only static methods) and save the instances in a map. You can then use

map[name].get(1)

to select one of them.

[EDIT] "$name" is a GString and as such a valid statement. "$name".foo() means "call the method foo() of the class GString.

Aaron Digulla
I was hoping to find out if there was a "Groovy" way of doing Class.forName, similar to how they made reflection on methods so easy. I do appreciate your answer and suspect that this might be the only way.
John Wagenleitner
@John: No, that's not possible. I asked on the Groovy ML. You have to call Class.forName() because "$name" is a GString and Groovy doesn't try to be smart about the contents of the variable "name".
Aaron Digulla
@Aaron - thanks, I read the thread on the Groovy ML and that just the info I was looking for.
John Wagenleitner
It doesn't work with classes defined in the current script, does it? class TestName {}Class.forName("TestName")
Mykola Golubyev
Sure. Why not? The script is read, compiled and then run. At the time when it is run, all the class files exist, so Class.forName() can find them.
Aaron Digulla
+6  A: 

As suggested by Guillaume Laforge on Groovy ML,

("Foo" as Class).get(i)

would give the same result.

I've tested with this code:

def name = "java.lang.Integer"
def s = ("$name" as Class).parseInt("10")
println s
chanwit
@chanwit - thanks for the example it was very helpful.
John Wagenleitner
The first example ("Foo" as Class).get(i) does not seem to work in grails to dynamically load a domain class.
Scott Warren
This works in grails 1.3.4 grailsApplication.classLoader.loadClass(name);
Scott Warren
+1  A: 

Here's another way

import org.codehaus.groovy.grails.commons.ApplicationHolder as AH

def target = application.domainClasses.find{it.name == 'ClassName'}
target.clazz.invokeMethod("Method",args)

With this you don't need to specify the package name. Be careful though if you have the same class name in two different packages.

ken