d工厂取信息
原创
©著作权归作者所有:来自51CTO博客作者fqbqrr的原创作品,请联系作者获取转载授权,否则将追究法律责任
工作时,创建类(使用自己包装器,或可用Object.factory
并用动态调度
函数把它转换为某个通用接口
),然后使用动态函数
.就像:
// 注意: 工厂要`模块+类`全名
auto foo = cast(MyDynamic) Object.factory("mymodule.Foo");
assert(foo !is null); // 找不到,为`无效`.
foo.call("my_method", ["arg", "arg2", ...]);
循环allMembers
,基于运行时
串调用.通过遍历ModuleInfo
来获取所有实现接口
的类列表
.
1,使用__traits
编译时反射(MyDynamicImplementation)
2,使用ModuleInfo
和ClassInfo(getAllDynamicClasses
)来运行时反射
3,用户定义的属性(isDynamicallyAvailable)
4,使用动态
数据调用方法(MyDynamicImplementation
,使用ReturnType,ParameterTypeTuple
,如果有兴趣,还有Variant
的注释代码)
4,替代多重
继承,同时使用接口
和mixin
模板.
module dynamicstuff;
import std.variant;
import std.conv;
import std.traits;
// 接口,这样它就不会妨碍`多重`继承
interface MyDynamic {
Variant callMethod(string method, string[] arguments);
}
enum DynamicallyAvailable;
//用户定义注解来查看是否可用`该方法`
// 查看`上面`属性是否在`成员`上
bool isDynamicallyAvailable(alias member)() {
// 取属性
foreach(annotation; __traits(getAttributes, member))
static if(is(annotation == DynamicallyAvailable))
return true;
return false;
}
alias Helper(alias T) = T;
// 反射时更短.
mixin template MyDynamicImplementation() {
override Variant callMethod(string methodNameWanted, string[] arguments) {
foreach(memberName; __traits(allMembers, typeof(this))) {
if(memberName != methodNameWanted)
continue;
static if(__traits(compiles, __traits(getMember, this, memberName))) {
//过滤私成员
alias member = Helper!(__traits(getMember, this, memberName));//可用`member`
// 只对`可用`的函数感兴趣
static if(is(typeof(member) == function) && isDynamicallyAvailable!member) {
// 调用它.
ParameterTypeTuple!member functionArguments;
// 不变,不编译
foreach(index, ref arg; functionArguments) {
if(index >= arguments.length)
throw new Exception("参数不够" ~ methodNameWanted);
// 这里为串.
arg = to!(typeof(arg))(arguments[index]);
// arg = arguments[index].get!(typeof(arg));
}
Variant returnValue;
// 取返回值,检查空.
static if(is(ReturnType!member == void))
member(functionArguments);
else
returnValue = member(functionArguments);
return returnValue;
}
}
}
throw new Exception("无此" ~ methodNameWanted);
}
}
// 可调用
class MyClass : MyDynamic {
mixin MyDynamicImplementation!();
@DynamicallyAvailable
void method(int param) {
import std.stdio;
writeln("哈哈", param);
}
}
class MySubClass : MyClass {
// 子类,用插件来注册
mixin MyDynamicImplementation!();
@DynamicallyAvailable
void childMethod(int param) {
import std.stdio;
writeln("子类哈哈", param);
}
}
void main(string[] args) {
MyDynamic mc;
if(args.length > 1)
mc = cast(MyDynamic) Object.factory(args[1]); //全名.
if(mc is null)
throw new Exception("非动态" ~ to!string(getAllDynamicClasses()));
// 方法列表,插件模板
mc.callMethod(args[2], args[3 .. $]);
}
/*
运行时取类列表
*/
string[] getAllDynamicClasses() {
string[] list;
// 取`object.d`中的`ModuleInfo`
foreach(mod; ModuleInfo) {
classList: foreach(classInfo; mod.localClasses) {
// 顶级类
if(doesClassMatch(classInfo))
list ~= classInfo.name;
}
}
return list;
}
// 运行时信息
bool doesClassMatch(ClassInfo classInfo) {
foreach(iface; classInfo.interfaces) {
// 全名
if(iface.classinfo.name == "dynamicstuff.MyDynamic") {
return true;
}
}
// 可能在基类.
if(classInfo.base !is null)
return doesClassMatch(classInfo.base);
return false;
}