d工厂取信息

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