56用d编程用户定义属性
可给任何声明(结构,类,变量)赋值属性,然后编译时访问他们来改变编译的方式.用户定义属性完全是编译时特征.
@Encrypted string name;
可以指定多个属性.这样:
@Encrypted @Colored string lastName;
@(Encrypted,Colored) string address;
属性名可为类型名,用户定义值,基本类型
.禁止属性包含像42字样的字面量(意思不明).
struct Encrypted {
}
enum Color { black, blue, red }
struct Colored {
Color color;
}
void main() {
@Encrypted int a;//类型名
@Encrypted() int b;//对象
@Colored(Color.blue) int c;//对象
@(42) int d;//禁止
}
a,b的属性不同.
这样获取_ _traits(getAttributes)
属性,属性含义根据需要而定.
import std.stdio;
// ...
struct Person {
@Encrypted @Colored(Color.blue) string name;
string lastName;
@Colored(Color.red) string address;
}
void main() {
foreach (attr; __traits(getAttributes, Person.name)) {//取`人.名`的属性
writeln(attr.stringof);
}
}
_ _traits(allMembers)
按串取类型/模块的成员
_ _traits(getMember)
访问成员时取一个符号.
import std.string;
// ...
void main() {
foreach (memberName; __traits(allMembers, Person)) {
writef("属性%-8s:", memberName);
foreach (attr; __traits(getAttributes, __traits(getMember, Person, memberName))) {
writef(" %s", attr.stringof);
}
writeln();
}
}
_ _traits(getMember, Person, "name")
生成符号Person.name
std.traits.hasUDA
确定是否有用户属性.
import std.traits;
// ...
static assert(hasUDA!(Person.name, Encrypted));//有`加密`属性
static assert(hasUDA!(Person.name, Colored));
static assert(hasUDA!(Person.name, Colored(Color.blue)));
示例:
void printAsXML(T)(T object) {
// ...
foreach (member; __traits(allMembers, T)) {
//T,类型的所有成员
string value =__traits(getMember, object, member).to!string; //成员值转为串
static if (hasUDA!(__traits(getMember, T, member),Encrypted)) {//是否有加密属性,使用的是符号
//按符号取成员,例如`Person.name`
value = value.encrypted.to!string;
}//加密
writefln(` <%1$s color="%2$s">%3$s</%1$s>`, member,colorAttributeOf!(T, member), value);
}
//都是展开的
}
颜色属性:
foreach (attr; __traits(getAttributes,__traits(getMember, T, memberName))) {//取属性,符号
static if (is (typeof(attr) == Colored)) {
return attr.color;
}
}
return Color.black;
}
等价于:
void printAsXML_Person(Person object) {
// ...
{
string value = object.name.to!string;
value = value.encrypted.to!string;
writefln(` <%1$s color="%2$s">%3$s</%1$s>`,
"name", Color.blue, value);
}
{
string value = object.lastName.to!string;
writefln(` <%1$s color="%2$s">%3$s</%1$s>`,
"lastName", Color.black, value);
}
{
string value = object.address.to!string;
writefln(` <%1$s color="%2$s">%3$s</%1$s>`,
"address", Color.red, value);
}
}
完整程序:
import std.stdio;
import std.string;
import std.algorithm;
import std.conv;
import std.traits;
struct Encrypted {//一个构就可以了
}
enum Color { black, blue, red }//枚举
struct Colored {//默认颜色为黑
Color color;
}
struct Person {
@Encrypted @Colored(Color.blue) string name;
//加密,颜色为蓝
string lastName;//无
@Colored(Color.red) string address;//红颜色
}
//有颜色返回指定颜色,无,为黑色
Color colorAttributeOf(T, string memberName)() {
auto result = Color.black;
foreach (attr;__traits(getAttributes,__traits(getMember, T, memberName))) {
static if (is (typeof(attr) == Colored)) {
result = attr.color;
}
}
return result;
}
auto encrypted(string value) {//简单加密
return value.map!(a => dchar(a + 1));
}
unittest {
assert("abcdefghij".encrypted.equal("bcdefghijk"));
}
void printAsXML(T)(T object) {//见上
writefln("<%s>", T.stringof);
scope(exit) writefln("</%s>", T.stringof);
foreach (member; __traits(allMembers, T)) {
string value =__traits(getMember, object, member).to!string;
static if (hasUDA!(__traits(getMember, T, member),Encrypted)) {
value = value.encrypted.to!string;
}
writefln(` <%1$s color="%2$s">%3$s</%1$s>`,member, colorAttributeOf!(T, member), value);
}
}
void main() {
auto people = [ Person("Alice", "Davignon", "Avignon"),Person("Ben", "de Bordeaux", "Bordeaux") ];
foreach (person; people) {printAsXML(person);}
}
用户定义属性可以不改变程序只改变属性声明.如
struct Person {
@Encrypted {
string name;
string lastName;
string address;
}//都加密了
}
// ...
printAsXML(Person("Cindy","de Cannes", "Cannes"));
也可同其他类型连用
struct Data {
@Colored(Color.blue) string message;
}
// ...
printAsXML(Data("hello world"));
用户定义属性可赋值给任意类型,可为类型名或值(对象)
可通过hasUDA 和 __traits(getAttributes)
来改变编译程序方式
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现