1

嘿嘿,

在通过一些泛型进行编码时,我偶然发现了我的一个泛型函数的问题。我有2种这样的

import std/options
import norm

type
    A = ref object of Model
        name: string
    B = ref object of Model
        name: string
        myA: Option[A]

norm是用于 sqlite 的 nim 中的 ORM,我只需拥有从 Model 继承的类型并调用table()它,就可以在编译时获取模型所属的 sql-tablename。

由于各种原因,我希望能够找出给定模型链接到的所有表的名称。在这种情况下,B链接到 type A,但我需要在编译时调用以获取该表名(如果正在使用 pragma A.table(),这可能是任何东西)。{.tableName.}

但是,我似乎找不到访问我的类型的方法,因为我无法在编译时调用模块的典型get()方法。options我的出路是什么?

4

1 回答 1

1

感谢 nim-discord 服务器上非常乐于助人的人(在那里大声疾呼),我能够解决这个问题。事实上,我只是提出了这个问题,所以我自己可以更轻松地用谷歌搜索答案。

您可以使用该[typetraits][1]库及其genericParams函数。

genericParams(B).get(0)

使用 genericParams 作为工具,您可以做一些有趣的事情,比如在编译时迭代一个类型的所有字段(不是实例!),检查给定字段是否是模型的选项并比较表名

proc getRelatedFieldName[M: Model, O:Model](targetType: typedesc[O], sourceType: typedesc[M]): Option[string] =
    let source = sourceType()
    for sourceFieldName, sourceFieldValue in source[].fieldPairs:
        when sourceFieldValue is Option:
            when sourceFieldValue.get() is Model:
                when O.table() == genericParams(sourceFieldValue.type()).get(0).table():
                    return some(sourceFieldName) 

    return none(string)


echo A.getRelatedFieldName(B) # returns "some('myA')"

于 2022-01-07T23:01:07.323 回答