d从串名调用类

原文

import std.stdio;

class Math {
  static string noArgs(string[] s) { writeln(s); return ""; }
  static string withOneArg(string[] s) { writeln(s); return ""; }
  static string withTwoArgs(string[] s) { writeln(s); return ""; }
}

class String {
  static string oneArg(string[] s) { return null; }
}

string execute(string what, string[] params) {
  import std.string;
  auto parts = what.split(".");
  auto className = parts[0];
  auto methodName = parts[1];

  import std.typetuple;
  switch(className) {
    default: assert(0, "未知类");
    foreach(possibleClass; TypeTuple!(Math, String)) {//可能类.
      case possibleClass.stringof:
        switch(methodName) {
          default: assert(0, "未知方法");
          foreach(memberName; __traits(derivedMembers, possibleClass)) {//成员名
            case memberName:
              return __traits(getMember, possibleClass, memberName)(params);//调用
            break;
          }
        }
      break;
    }
  }
  assert(0);
}

void main() {
  execute("Math.withOneArg", ["cool"]);
  execute("String.oneArg", ["cool"]);
}

请注意,没有使用mixin 式.我没有从中获取类的实例,而是用TypeTuple包含需要的类.在不同域内使用时,比mixin更好,因为不太可能找到名类;如果possibleClasses是从不同模块执行的编译时参数,则类列表仍然有效,而串列表看到未定义标识错误,因为库模块不导入你的用户模块.

我删除的另一个mixin是生成若的那个.这很疯狂,
可有编译时每一,__traits等.甚至可在他们里面放case.
所以,只需在要比较的运行时变量上写普通switch语句,把它放在foreach里面循环搜索编译时东西,case that_loop_var:然后就好了.
同样,我使用__traits(getMember)而不是mixin串来调用该方法.来避免名字冲突,并且代码更简洁.如果需要,还可处理重载(使用__traits(getOverloads)而不是__traits(getMember),可循环遍历每个重载并匹配参数类型).
最后,允许在其他case语句中的嵌套switches.如果要跳出外部循环或switch,又不想出现歧义,可标记循环和开关,并使用break label_name_here;来退出.continue一样.
std.traits.ParameterTypeTupleReturnType很好用.

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