使用参数在Groovy中动态创建方法

时间:2014-01-10 20:59:26

标签: java groovy supercsv

我要求我使用SuperCSV读取csv文件并映射到对象。

SuperCSV有一个要求,如果头部指定了一个字段名称“firstName”,它需要在类中使用setFirstName()方法,否则会引发异常。

现在,如果我使用Groovy bean,那么我不需要声明所有这些方法只是声明变量应该适用于SuperCSV。

但我一直在寻找一个更加动态的解决方案,我们甚至不需要声明这些变量。

例如,只需在飞行中创建一个对象,并使用groovy的动态方法创建功能,SuperCSV将能够找到设置者。

我查看了各种选项,例如Expando,ExpandoMetaClass,但这些选项并没有达到我的目的。

任何答案都将不胜感激。

以下代码片段对我有用,可以帮助减少大量代码和不必要的逻辑:

    static def testBeanReader()
{
    ICsvBeanReader beanReader = null;
    try 
    {
        beanReader = new CsvBeanReader(new FileReader("src/test.csv"),
                                 CsvPreference.STANDARD_PREFERENCE);                      
    }
    catch(Exception e)      
    {

    }

    final String[] header = VirtualObject.getHeaders();
    final CellProcessor[] processors = VirtualObject.getProcessors();

    //Class c1 = createNewClass()

    //String s = createClass()
    def list = ["name", "age"]
    def c = (new GroovyShell().evaluate(createClass(list)) as Class)
    //println(c.methods.grep {it.name.startsWith("get")})

    GroovyObject groovyObject = (GroovyObject)(beanReader.read(c, header, processors))
    Object[] args = {};
    println(groovyObject.getProperty("name"))

}

     static def createClass(def list)
{
    String classDeclaration = "\nclass Test {\n"
    list.each 
    {
        classDeclaration+="def $it\n"
    } 

    classDeclaration+= """
    }
            return Test.class
                              """
    return  classDeclaration
}

这对于supercsv的东西,但可以用于语法

几乎没有变化的通用java对象

1 个答案:

答案 0 :(得分:2)

不能使用Groovy shell来动态构造这些类。

def c = (new GroovyShell().evaluate("""
class Test {
    def fileName // list properties here
}
return Test.class
""") as Class)

println(c.methods.grep {it.name.startsWith("set")})

def m = (c as Class).getMethod("setFileName", [Object] as Class[])
// We, and I suppose SuperCSV, can access method via Reflexion API

它不安全,但它会动态创建Java兼容类。

我不熟悉SuperCSV,但我认为当Expando或MetaClass解决方案使用Groovy元对象协议时,它应该像反射一样使用smth。

GroovyShell(或GroovyClassLoader)将能够创建正常的类,具有工作的Reflexion。

已编辑:说明生成的类的动态特性。我们首先创建类源(正如我们所希望的,从运行时信息中,来自CSV标题),然后使用它。

def createClassDeclaration()
{
    String classDeclaration = "\nclass Test {\n"
    // Here you can use your runtime information, schema, array of fields, getted from any source.
    10.times {
        classDeclaration+="def field$it\n" // declares def field1, field2, ... etc
    }
    classDeclaration += """
    }
    return Test.class
    """
    println(classDeclaration)
    return classDeclaration
}
def compile(String s)
{
    def c = (new GroovyShell().evaluate(s) as Class)
    def m = (c as Class).getMethod("setField1", [Object] as Class[])
    assert m
    println(c.methods.grep {it.name.startsWith("set")})

}

compile(createClassDeclaration())