02序化构

原地址

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

    static foreach(number; [1, 2, 3, 4, 5])
    {
        writeln(number);
    }
}
//展开为:
void main()
{
    import std.stdio : writeln;

    writeln(1);
    writeln(2);
    writeln(3);
    writeln(4);
    writeln(5);
}

static foreach不会创建,其在编译时如上展开.因而可能有问题,因此一般用{{|}}来配合静每一:

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

    static foreach(number; [1, 2, 3])
    {{
        int 复杂式 = number + number;
        writeln(复杂式);
    }}
}
//展开为:
void main()
{
    import std.stdio : writeln;

    {
        int 复杂式 = 1 + 1;
        writeln(复杂式);
    }

    {
        int 复杂式 = 2 + 2;
        writeln(复杂式);
    }

    {
        int 复杂式 = 3 + 3;
        writeln(复杂式);
    }
}

别名,可与任意符号(如函数)一起用,而不仅是类型.

struct SomeStruct
{
    int a;
}

alias SStruct = SomeStruct;

void main()
{
    // 只是别名.
    SStruct a = SomeStruct(200);
}

清单常量:仅在编译时存在的不变变量.出现时,复制它.与普通变量一样,只是有前缀:

enum float PI = 3.14;
enum AGE = 200;
//可自动推导.

他们是编译时存储,且静如可访问的,因而重要且有用.注意:

enum MyArray = [1, 2, 3, 4];
//1,表示数组时,
static immutable MyArray = [1, 2, 3, 4];
//2,只表示1个时,这样就只复制一次,从而`s 是 t`.
void main()
{
    auto s = MyArray;
    auto t = MyArray;//1,会复制2次,
    assert(s !is t);
}

清单常量可为模板.因而我们可实现自己的特征.

enum myIsBoolean(T) = is(T == bool);
//可为模板.

enum isStringABoolean  = myIsBoolean!string; // 假
enum isBooleanABoolean = myIsBoolean!bool;   // 真

static assert(!isStringABoolean);
static assert(isBooleanABoolean);

有点类似C++概念了.现在序化构,先检查是否是原始类型:

enum isPrimitiveType(T) = isNumeric!T || is(T == bool) || is(T == string);

现在这样:

JSONValue serialise(T)(T value)
{
    static if(isPrimitiveType!T)
    {
        return JSONValue(value);
    }
    else static if(is(T == struct))
    {
        JSONValue toReturn;

        // 用`的元组`来遍历成员.
        static foreach(member; T.tupleof)
        {{
            alias MemberType = typeof(member);
            pragma(msg, MemberType.stringof);
        }}//{{}}来避免展开问题.

        return toReturn;//
    }
}

先是类型,接着取名字:

{{
    alias MemberType = typeof(member);

    // 编译器可推导为串.
    const MemberName = __traits(identifier, member);
    pragma(msg,MemberName~"是"~MemberType.stringof~"类型");
}}

插件来将:

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

转为:

string memberValue = value.name;
int memberValue = value.age;

最后,{{}}中内容为:

{{
    alias MemberType = typeof(member);
    const MemberName = __traits(identifier, member);
    MemberType memberValue = mixin("value." ~ MemberName);

    // toReturn是个`数格`,用`成员名`为键,`成员值`为值.
    toReturn[MemberName] = serialise(memberValue);
}}

数格值对象,就是个统一对象.所有类型均归一化为该类型.

void main()
{
    import std.stdio;
    
    // 用`动`指定类型
    auto json = serialise(Person("Bradley", 20));
    writeln(json);

    /*
    输出:
        {"age":20,"name":"Bradley"}
    */
}

接着,解序化结构:

T deserialise(T)(JSONValue json)
{
    /* 前面原始类型省略了*/
    else static if(is(T == struct))
    {
        T toReturn;//返回类型.

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

            MemberType memberValue = deserialise!MemberType(json[MemberName]);
            // 整个语句是`插件`,所以`插件`中也要有`分号`;
            mixin("toReturn." ~ MemberName ~ " = memberValue;");
            // 如:
            // toReturn.name = memberValue;
            // toReturn.age = memberValue;
        }}

        return toReturn;
    }
    /**/
}

测试:

void main()
{
    import std.stdio : writeln;
    
    auto json = serialise(Person("Bradley", 20));
    writeln("数格: ", json);
    
    auto person = deserialise!Person(json);
    writeln("人: ", person);

    /*
    输出:
        数格: {"age":20,"name":"Bradley"}
        人: Person("Bradley", 20)
    */
}
上一篇:redis专题六:redis数据类型之sorted_set


下一篇:day39 redis 数据类型 Set集合、SortedSet有序集合