天天看点

d工厂取信息

工作时,创建类(使用自己包装器,或可用​

​Object.factory​

​​并用​

​动态调度​

​​函数把它转换为某个​

​通用接口​

​​),然后使用​

​动态函数​

​.就像:

// 注意: 工厂要`模块+类`全名
auto foo = cast(MyDynamic) Object.factory("mymodule.Foo");
assert(foo !is null); // 找不到,为`无效`.
foo.call("my_method", ["arg", "arg2", ...]);      
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;
}