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.ParameterTypeTuple和ReturnType很好用.
浙公网安备 33010602011771号