D 语言:迭代结构成员并检查 UDA(运行时反射)
D language: Iterate over members of a struct and check a UDA (runtime reflection)
在 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;
}
我该怎么做?
有两种方法可以做到这一点。如果它是一个结构,我会选择 __traits(allMembers, T)
,但是对于 classes 我会选择 __traits(derivedMembers, T)
以确保您不会从对象继承或其他实例中获得垃圾你不感兴趣(如果你想继承 allMembers 也可以)。
对于可能是结构或 class 的一般情况,但您不确定,为了安全起见,我会选择 derivedMembers
。
你应该做的是使用 __traits(compiles)
来防止私有成员,因为 allMembers
和 derivedMembers
也会 return 私有成员等
参见: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;
}
注意:我没有实现模式。
尽管您可以使用:
在 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;
}
我该怎么做?
有两种方法可以做到这一点。如果它是一个结构,我会选择 __traits(allMembers, T)
,但是对于 classes 我会选择 __traits(derivedMembers, T)
以确保您不会从对象继承或其他实例中获得垃圾你不感兴趣(如果你想继承 allMembers 也可以)。
对于可能是结构或 class 的一般情况,但您不确定,为了安全起见,我会选择 derivedMembers
。
你应该做的是使用 __traits(compiles)
来防止私有成员,因为 allMembers
和 derivedMembers
也会 return 私有成员等
参见: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;
}
注意:我没有实现模式。
尽管您可以使用: