【问题标题】:Kotlin reflection - creating objects from CSVKotlin 反射 - 从 CSV 创建对象
【发布时间】:2020-10-26 03:18:51
【问题描述】:

我有一个名为 Member 的数据类:

data class Member(){
    val first_name: String
    val last_name: String
    //30 more

    //a few simple methods
}

我正在尝试导入 CSV 文件。文件的每一行都包含我想用来实例化成员的字段。

fun ReadCsvFileKotlin() {
    val csvFile = "C:\\Data.csv"
    var memberList = mutableListOf<Member>()
    var reader = File(csvFile).readLines()
    var mbr: Member
    class Member(val p: Int)
    val prop = Member::p
    for(line in reader){
        val mbrProperties = line.split(",")
        for(i in 0..mbrProperties.lastIndex){
            //assign mbrProperties[i] to mbr property
            //mbrProperties[0] = "Bob"
            //mbr.first_name = "Bob"
            //Member::p = mbrProperties[i]
    }
    memberList.add(mbr)
}

我已经完成了我的研究,但我无法完全理解我所阅读的信息,并且无法弥合我现在和我想成为的地方之间的差距。

任何建议将不胜感激!欢迎带我浏览或使用我的示例代码给我示例。

背景:我正在为一个网站进行自动化测试。在执行每个测试之前,从列表中选择满足必要测试标准的成员,该列表由 CSV 文件填充。我希望以这种方式创建我的成员对象,以随着测试范围的扩大和添加其他标准(和成员类字段)而减少维护开销。

为什么我要以我现在的方式做这些事情?因为我还有很多东西要学......(所以,如果你看到更好的方法,请不吝赐教!)

谢谢!

【问题讨论】:

    标签: csv reflection kotlin


    【解决方案1】:

    解决这个问题的最简单方法是根本不使用反射。您可以将属性值直接传递给类构造函数:

    data class Member(val firstName: String, val lastName: String)
    
    fun readCsvFileKotlin() {
        // ...
        for (line in reader) {
            val mbrProperties = line.split(",") 
            memberList.add(Member(mbrProperties[0], mbrProperties[1]))
        }
    }
    

    如果要通过反射设置属性,需要将其声明为var而不是val,以便在创建对象后更改它们。然后可以在属性对象上使用set方法来改变属性值:

    data class Member(var firstName: String? = null, var lastName: String? = null)
    
    fun readCsvFileKotlin() {
        // ...
        val prop = Member::firstName
        for (line in reader) { 
            val mbrProperties = line.split(",") 
            val member = Member()
            prop.set(member, mbrProperties[0])
            memberList.add(member)
        }
    }
    

    【讨论】:

    • 是否有遍历类属性并为每个属性设置它们?
    【解决方案2】:

    虽然我确实玩弄了 yole 的回应,并进一步反思,但我找到了一种更好的方法来处理我的问题。

    作为一个经验不足的程序员,我试图使用错误的工具来完成这项工作。我想要一个对象,它具有许多不同的自动化测试所需的功能,模拟用户 - 在每个实例中我想要的代码,无论我是否需要它来进行测试。

    但我想要的是数据的灵活性。因此,我不再使用具有越来越多属性的单个对象或多个对象,每个对象都自定义到特定的数据集,而是选择了一个属性。最好的解决方案是键/值对属性。如果我的 Kotlin 语言生疏了,我深表歉意,我在过去两年多的时间里一直专注于 python。字典?

    基本上,我剥离了 csv 的标题,将其作为字典/键、值对映射到每一行,然后在实例化对象并将对象添加到列表时添加。如果直接查询数据库而不是使用 csv 或 Excel 文件,则类似。

    只要我不为我的结果编写更改表的列名的查询,并且我知道数据库中的列名(它们不会很快改变),我已经在映射它进程和/或 gui(或两者)的数据非常好,没有反射开销。

    【讨论】:

      【解决方案3】:

      如果您仍然希望这样做,我创建了自己的 CSV 库,该库使用反射直接从 CSV 输入实例化 POJO,并且比我测试过的常规解析器(称为 Kotlin CSV Stream)更好地管理 CSV 中的错误

      我实际上是在放弃传统解析器后创建的,因为它们都不能满足我的需求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-01
        • 2015-07-30
        • 1970-01-01
        • 2016-11-14
        • 2023-02-14
        • 2012-05-15
        • 2017-05-04
        • 1970-01-01
        相关资源
        最近更新 更多