d查找特定属性的所有函数

原文
代码在此
输出:

Processing: module main
Processing: module object
Processing: module c
Processing: module attr
test2() has sillyWalk
main() has sillyWalk

需要快速查看c.d,b.dmain.d以了解其用法.main.donEach函数处理每次帮助函数找到的命中,这里只是打印名.在main函数中,你会看到一个疯狂mixin(__MODULE__),用来按迭代起点当前模块引用.
注意,main.d文件顶部有module project.main;一行,如果模块名仅为main,那么mixin黑客会混淆main模块与函数.
现在,注意attr.d.

module attr;
struct sillyWalk { int i; }

enum isSillyWalk(alias T) = is(typeof(T) == sillyWalk);

import std.typetuple;
alias hasSillyWalk(alias what) = anySatisfy!(isSillyWalk, __traits(getAttributes, what));
enum hasSillyWalk(what) = false;

alias helper(alias T) = T;
alias helper(T) = T;

void allWithSillyWalk(alias a, alias onEach)() {
    pragma(msg, "Processing: " ~ a.stringof);
    foreach(memberName; __traits(allMembers, a)) {
        // 保证避免错误
        static if(__traits(compiles, __traits(getMember, a, memberName))) {
            alias member = helper!(__traits(getMember, a, memberName));

            // pragma(msg, "查看" ~ memberName);
            import std.string;
            static if(!is(typeof(member)) && member.stringof.startsWith("module ")) {
                enum mn = member.stringof["module ".length .. $];
                mixin("import " ~ mn ~ ";");
                allWithSillyWalk!(mixin(mn), onEach);
            }

            static if(hasSillyWalk!(member)) {
                onEach!member;
            }
        }
    }
}

首先,有属性定义一些帮助器来检测它的存在.只需扫描属性元组来查找感兴趣类型.
helper模板是缩写重复__traits(getMember)调用的技巧,它只是别名更好名,同时避免编译器中出现愚蠢的解析错误.
最后,有了步行者.它循环了allMembers.
接着,第一个static if只是确保可真正获得想要获得成员.没有它,它会在获取自动导入object模块的私有成员时抛错误.

函数结尾也很简单,它只是在每个元素上调用onEach.中间有点神奇:它检测到导入模块,在此导入,通过mixin(module)顶层技巧访问它,然后通过导入图递归.

dmd main.d attr.d b.d c.d

也有些限制:
1,可以进入类/结构成员,但这里没有实现.不过非常简单:如果成员是类,也只需递归进入它.
2,如果模块成员共享名,则可能会中断,如main示例.用带有一些包点唯一模块名来解决问题它.
3,它不会下降函数本地导入,
使用UDA添加代码总是很麻烦,在此更是,因为onEach具有域的函数.不过,也许可构建全局关联闭包

void delegate()[string] handlers; 
/* ... */ 
handlers[memberName] = &localHandlerForThis;

大多数D代码,不需要如上遍历导入树,只是要求你,在使用它的单个聚集或模块中:

mixin UdaHandler!T;

或在每个之后:

mixin RegisterSerializableClass!MyClass;
posted @   zjh6  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示