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)
*/
}
随着用定属
的添加,代码越复杂
.要合理组织好.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现