D语言:迭代结构的成员并检查UDA(运行时反射)

时间:2016-12-21 06:19:27

标签: reflection d

在D语言中,我想迭代结构并执行特定于附加到每个成员的每个注释的逻辑。实施例

struct Pattern {
    string pattern;
}

string Max {
    int max;
}

string Min {
    int min;
}

struct StructToValidate {
    @Pattern("^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$")
    string phone;

    @Max(20)
    @Min(3)
    int someValue;
}

然后在函数中,执行以下操作:

int main() {
    StructToValidate struct;

    // begin pseudocode
    // for each member of struct mem = [phone, someValue] {
    //     if (hasUDA!(mem, Pattern)) {
    //         do stuff like validation on the runtime value of this member
    //     } else if (hasUDA!(mem, Min)) {
    //         ...
    //     } else if (hasUDA!(mem, Max)) {
    //         ...
    //     }
    // }
    //
    return 0;
}

我该怎么做?

1 个答案:

答案 0 :(得分:3)

有两种方法可以做到。如果它是一个结构,我会选择__traits(allMembers, T),但对于课程,我会选择__traits(derivedMembers, T)以确保您不会从对象继承中获取垃圾或者从你不感兴趣的其他情况下(如果你想要不受欢迎,所有成员也会工作)。

对于可能是结构或类的一般情况,但您不确定,为了安全起见,我会选择derivedMembers

你应该做的是使用__traits(compiles)来防范私人成员,因为allMembersderivedMembers也将返回私人等。

请参阅:https://dlang.org/spec/traits.html#compiles

我可能会这样做:

void validate(T)(T toValidate) {
    import std.traits;

    foreach (member; __traits(allMembers, T)) { // Loops through all members of "T"
        static if(__traits(compiles, __traits(getMember, T, member))) { // Guards against private members
            static if (mixin("hasUDA!(" ~ T.stringof ~ "." ~ member ~ ", Pattern)")) { // Checks if the member has the UDA "Pattern"
                // TODO: pattern
            }

            static if (mixin("hasUDA!(" ~ T.stringof ~ "." ~ member ~ ", Min)")) { // Checks if the member has the UDA "Min"
                // Gets the value from the UDA and stores it in a variable that we can use at runtime.
                auto value = getUDAs!(mixin(T.stringof ~ "." ~ member), Min)[0].min;

                // Creates an assert for validating the member's value.
                mixin("assert(toValidate." ~ member ~ " >= value);");
            }

            static if (mixin("hasUDA!(" ~ T.stringof ~ "." ~ member ~ ", Max)")) { // Checks if the member has the UDA "Max"
                // Gets the value from the UDA and stores it in a variable that we can use at runtime.
                auto value = getUDAs!(mixin(T.stringof ~ "." ~ member), Max)[0].max;

                // Creates an assert for validating the member's value.
                mixin("assert(toValidate." ~ member ~ " <= value);");
            }
        }
    }
}

然后您可以像这样使用:

int main() {
    StructToValidate structToValidate;

    validate(structToValidate);

    return 0;
}

注意:我没有实现模式。

虽然您可以使用:

https://dlang.org/phobos/std_regex.html