Java教程

d05用用定属来自定义

本文主要是介绍d05用用定属来自定义,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

原文
D用定属可以为构/原始类型/编译时执行函数(返回值).
@TypeName附加,用__traits(getAttributes)来取用定属.

enum AnEnum{a}
struct AStruct{}
class AClass{}

int FunctionThatReturnsTheUDAValue(){ return 0; }

@AnEnum
@AStruct
@AClass
@FunctionThatReturnsTheUDAValue
struct Test{}

void main()
{
    import std.traits;
    // __traits(getAttributes)返回符号上的所有`用定属`元组
    static foreach(uda; __traits(getAttributes, Test))
        pragma(msg, uda);

    /* 
        输出:
            AnEnum
            AStruct
            AClass
            0
    */
}

还有std.traits#hasUDA和std.traits#getUDAs,来有/取用定属.std.traits#getSymbolsByUDA这个也很方便.

struct UsefulUDA
{
    string some;
    int data;
}

struct NeverUsedUDA
{
}

struct MultiUDA
{
    string data;
}

@UsefulUDA("Foo", 21)
@MultiUDA("Use")
@MultiUDA("Me")
@(MultiUDA("Multiple"), MultiUDA("Times"))
struct MyStruct
{

}

void main()
{
    import std.traits : hasUDA, getUDAs;
    import std.stdio  : writeln, write;

    writeln("构有@UsefulUDA?: ", hasUDA!(MyStruct, UsefulUDA));
    writeln("@NeverUsedUDA呢?:    ", hasUDA!(MyStruct, NeverUsedUDA));

    // 可多次用UDAs,getUDAs返回所有.
    const UsefulUDA useful = getUDAs!(MyStruct, UsefulUDA)[0];//要用[0]取第1个.
    writeln(useful);

    // 多次遍历
    static foreach(uda; getUDAs!(MyStruct, MultiUDA))
        write(uda.data, " ");

    /* 
        输出:  
            构有@UsefulUDA?: true
            @NeverUsedUDA呢?:    false
            const(UsefulUDA)("Foo", 21)
            Use Me Multiple Times 
    */
}

我们用如下三个属性来更新序化器.

属性意思
@Ignore忽略字段
@Name自定义名字
@ByValue按值序化枚举,而非名字.

我们用来表示用定属.

struct ByValue {}
struct Ignore {}

struct Name
{
    string name;
}

// 保留`Person`,用它来比较`用定属`的输出
struct Person
{
    string name;
    int age;
    PersonType type;
}

struct PersonWithUDAs
{//带用定属的人.
    @Ignore
    string name;

    @Name("yearsOld")
    int age;

    @ByValue
    PersonType type;
}

实现@忽略

由于静每一(a)展开.a的合作不是很好.因而,得有点技巧.我们把静每一锁在检查是否忽略字段的静如之后.如下在序化构/类{{}}:

static foreach(member; T.tupleof)
{{
    alias MemberType = typeof(member);
    const MemberName = __traits(identifier, member);

    MemberType memberValue = mixin("value." ~ MemberName);

    //静每一,如果`没有`忽略字段.
    static if(!hasUDA!(member, Ignore))
    {
        toReturn[MemberName] = serialise(memberValue);
    }
}}

同样:反序化中这样:

static foreach(member; T.tupleof)
{{
    alias MemberType = typeof(member);
    const MemberName = __traits(identifier, member);

    static if(!hasUDA!(member, Ignore))
//但对大块代码,这很烦人.因为不能用`下`.
    {
        MemberType memberValue = deserialise!MemberType(json[MemberName]);

        mixin("toReturn." ~ MemberName ~ " = memberValue;");
    }
}}

目前还没有@名字段.

实现@名及@按值

static if(!hasUDA!(member, Ignore))
{//修改该函数内容为
    JSONValue serialised = serialise(memberValue); //存储在变量中,供未来用.
    static if(hasUDA!(member, Name))
    //需要时,用自定义名
    {
        const SerialiseName = getUDAs!(member, Name)[0].name;
        toReturn[SerialiseName] = serialised;
    }
    else // 否则用`字段名`
    {
        toReturn[MemberName] = serialised;
    }
}

反序化:

static if(!hasUDA!(member, Ignore))
{//修改这个块.
    static if(hasUDA!(member, Name))
    {//名字
        const SerialiseName = getUDAs!(member, Name)[0].name; 
        JSONValue value = json[SerialiseName];
    }
    else
    {
        JSONValue value = json[MemberName];
    }

    MemberType memberValue = deserialise!MemberType(value);

    mixin("toReturn." ~ MemberName ~ " = memberValue;");
}

按值:

//注意,在`忽略`中.
static if(!hasUDA!(member, Ignore))
{
    // 存储进变量
    static if(hasUDA!(member, ByValue) && is(MemberType == enum))
    {//按值.
        JSONValue serialised = JSONValue(memberValue);
    }
    else
    {//按名
        JSONValue serialised = serialise(memberValue);
    }
    static if(hasUDA!(member, Name))
    {//名字
        const SerialiseName = getUDAs!(member, Name)[0].name;
        toReturn[SerialiseName] = serialised;
    }
    else
    {
        toReturn[MemberName] = serialised;
    }
}

同样反序化:

static if(!hasUDA!(member, Ignore))
{//忽略
    static if(hasUDA!(member, Name))
    {//名字
        const SerialiseName = getUDAs!(member, Name)[0].name; 
        JSONValue value = json[SerialiseName];
    }
    else
    {
        JSONValue value = json[MemberName];
    }

    // 不能再用`解序化`了.因为假定`按名字串`存储枚.
    static if(hasUDA!(member, ByValue))
    {
        MemberType memberValue = value.integer.to!MemberType();
    }//转为成员类型.
    else
    {
        MemberType memberValue = deserialise!MemberType(value);
    }

    mixin("toReturn." ~ MemberName ~ " = memberValue;");
}

测试代码:

void main()
{
    import std.stdio : writeln;

    auto person     = Person("Bradley", 20, PersonType.Student);
    auto personUDA  = PersonWithUDAs("Bradley", 20, PersonType.Student);
    writeln(person.serialise());
    writeln(personUDA.serialise());

    writeln(person.serialise().deserialise!Person());
    writeln(personUDA.serialise().deserialise!PersonWithUDAs());

    /* 
        输出:
            {"age":20,"name":"Bradley","type":"Student"}
            {"type":1,"yearsOld":20}
            Person("Bradley", 20, Student)
            PersonWithUDAs("", 20, Student)
    */
}

随着用定属的添加,代码越复杂.要合理组织好.

这篇关于d05用用定属来自定义的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!