Create a Groovy class dynamically

后端 未结 2 1138
不知归路
不知归路 2021-01-14 10:00

Given a class name I would like to dynamically create a Groovy class add properties and methods to it. I create the new class using

instance = this.class.cla         


        
相关标签:
2条回答
  • 2021-01-14 10:34

    a nice variant would be to use the GroovyShell.

    def c = """ 
    package de.myCorp.test
    
    class Test {
        def a
        def b
        def c    
    
        Test(String c){ this.c = c}
    
        public String greet(){
            return "hello "+a
        }
    
        public void count(){
            (1..4).each{
                println it
            }
        }
    
    }
    
    def class UsingTest {
        Test mytest = null
    
        UsingTest (Test test){  this.mytest = test }
    
        def using(){
            mytest.greet();
        }
    
    }
    """
    
    
    GroovyShell gs = new GroovyShell()
    //I hope this is not a too bad hack ^^ 
    def erg = gs.evaluate(c+";['test':Test, 'using':UsingTest];")
    
    def testclass = erg["test"].newInstance("Charlotte on Ice")
        testclass.a = "hugo"
        testclass.b = "sepp"
    
    
    testclass.count() 
    assert testclass.greet() == "hello hugo"
    
    assert testclass.c == "Charlotte on Ice"
    assert testclass.class.name == "de.myCorp.test.Test"
    
    
    def usingclass = erg['using'].newInstance(testclass)
    usingclass.mytest.a = "Fritzl"
    assert usingclass.using() == "hello Fritzl" 
    

    ...and especially notice the GroovyShell.evaluate(URI uri) types... GroovyShellDoc

    0 讨论(0)
  • 2021-01-14 10:46

    I have more or less been able to get it working by using GroovyClassLoader and SimpleTemplateEngine. here is the code:

    class ClassBuilder {
    
        GroovyClassLoader loader
        String name
        Class cls
        def imports
        def fields
        def methods
    
        def ClassBuilder(GroovyClassLoader loader) {
            this.loader = loader
            imports = []
            fields = [:]
            methods = [:]
        }
    
        def setName(String name) {
            this.name = name
        }
    
        def addImport(Class importClass) {
            imports << "${importClass.getPackage().getName()}" +
                    ".${importClass.getSimpleName()}"
        }
    
        def addField(String name, Class type) {
            fields[name] = type.simpleName
        }
    
        def addMethod(String name, Closure closure) {
            methods[name] = closure
        }
    
        def getCreatedClass() {
    
            def templateText = '''
    <%imports.each {%>import $it\n <% } %> 
    class $name
    {
    <%fields.each {%>    $it.value $it.key \n<% } %>
    }
    '''
            def data = [name: name, imports: imports, fields: fields]
    
            def engine = new groovy.text.SimpleTemplateEngine()
            def template = engine.createTemplate(templateText)
            def result = template.make(data)
            cls = loader.parseClass(result.toString())
            methods.each {
                cls.metaClass."$it.key" = it.value
            }
            return cls
        }
    }
    

    and here is an example of how I use it to create a class dynamically:

    import java.util.Calendar
    def builder = new ClassBuilder(this.class.classLoader)
    builder.setName("MyClass");
    
    builder.addImport(Calendar)
    
    builder.addField('field1', Integer)
    builder.addField('field2', Integer)
    
    builder.addMethod('sum') { field1 + field2 }
    
    builder.addMethod('product') { field1 * field2 }
    
    builder.addMethod('testCalendar') {
        println Calendar.getInstance().getTime()
    }
    
    Class myClass = builder.getCreatedClass()
    def myInstance = myClass.newInstance()
    
    myInstance.field1 = 1
    myInstance.field2 = 2
    
    println myInstance.sum()
    println myInstance.product()
    
    myInstance.setField2(1500)
    println myInstance.getField2()
    
    myInstance.testCalendar()
    
    0 讨论(0)
提交回复
热议问题