2016-12-21 6 views
2

D 언어에서는 구조체를 반복하고 각 멤버에 연결된 각 주석에 특정한 논리를 수행하려고합니다. 전의. 나는이 작업을 수행하려면 어떻게D 언어 : 구조체의 멤버를 반복하고 UDA (런타임 리플렉션)를 확인하십시오.

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; 
} 

:

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; 
} 

다음 함수에서

는 이런 일을합니까?

답변

3

두 가지 방법으로 할 수 있습니다. 구조체 인 경우 __traits(allMembers, T)으로 가고 싶지만 클래스의 경우 __traits(derivedMembers, T)과 같이 객체 상속 또는 다른 인스턴스에서 가비지를받지 못하게해야합니다 (원하는 경우 모든 회원들도 상속받을 것입니다).

구조체 또는 클래스가 될 수 있지만 확실하지 않은 일반적인 경우에는 안전을 위해 derivedMembers을 사용해야합니다.

은 당신이 생각해야 할 것은 allMembersderivedMembers도 음부 등을 반환하기 때문에, 개인 회원을 방지하기 위해 __traits(compiles)을 사용하는 것입니다

참조 : 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

+0

는 와우는 영리하다. Mixin 마법은 결코 나를 놀라게하지 않습니다. 나는 시간이 더있을 때 이것을 시도 할 것이다. – FatalCatharsis

+0

작동하는 경우 대답을 받아주십시오 :)하지만 문자열 믹스 인은 놀랍습니다. 무엇이든 할 수 있습니다. – Bauss

+0

매력처럼 작동합니다. 내가해야했던 유일한 조정은 elses를 제거하는 것이 었습니다. 그래서 멤버의 여러 속성들이 모두 처리 될 것입니다. – FatalCatharsis