Use Object.factory without requiring a cast to a specific type

I am trying to create a similar router for the Rails ActionDispatch router, which allows you to define a route similar to

map.get "/foo", :controller => "Foo", :action => "index"

which will then direct GET /footo FooController#index. Using this structure, you can use methods such as

map.resources :foos

which will call methods like

map.get "/foo", :controller => "Foo", :action => "index"
map.get "/foo/:id", :controller => "Foo", :action => "show"

etc.

In D, I was able to find a lot of reflective code needed to do the job, but not for everyone. In Ruby, I can do:

class Foo
  def bar
    "FOOO BAR!"
  end
end

f = Object.const_get("Foo")
f.new.__send__(:bar) #=> "FOOO BAR!"

What I tried to translate into

module foo;
import std.stdio;

class Foo {
  void bar() {
    writeln("FOO BAR!");
  }
}

void main() {
  auto foo = Object.factory("foo.Foo");
  __traits(getMember, foo, "bar");
}

But this does not work, because the compiler does not know what type foo, so the call #barfails at compile time. Wherever I saw Object.factory, they passed it to a certain type, so

module foo;
import std.stdio;

class Foo {
  void bar() {
    writeln("FOO BAR!");
  }
}

void main() {
  auto foo = cast(Foo) Object.factory("foo.Foo");
  __traits(getMember, foo, "bar");
}

. , , Object.factory? !

2 , , ,

module foo;
import std.stdio;

class MyDynamic {
  void call(C, T...)(C instance, string method, T args) {
    foreach(member; __traits(allMembers, C)) {
      writeln(member);
      if (member == method) {
        static if (__traits(compiles, __traits(getMember, instance, member)(args))) {
          __traits(getMember, instance, member)(args);
        }
        return;
      }
    }

    assert(0, "No method found");
  }
}

class Foo : MyDynamic {
  void bar() {
    writeln("FOO BAR!");
  }
}

void main() {
  auto foo = cast(MyDynamic) Object.factory("foo.Foo");
  assert(foo !is null);

  foo.call(foo, "bar");
}

. , , : https://github.com/jaredonline/action-pack

+4
1

, , factory . __traits (allMembers), . , , . - .

, ( Object.factory ), . - :

// IMPORTANT: Object.factory needs a full name - includes the module and class name!
auto foo = cast(MyDynamic) Object.factory("mymodule.Foo");
assert(foo !is null); // Object.factory can return null if it didn't find the class
// and cast can also return null if it wasn't actually of that interface type, so gotta check

foo.call("my_method", ["arg", "arg2", ...]);

, , module dynamicstuff; :

http://arsdnet.net/dcode/test46.d

loop allMembers, . , , , ModuleInfo. . , .

My web.d . , , . : https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/web.d#L2538

ParameterTypeTuple! func std.traits.

http://arsdnet.net/dcode/test46.d, , , . :

  • __traits (MyDynamicImplementation)
  • ModuleInfo ClassInfo (getAllDynamicClasses)
  • (isDynamicallyAvailable)
  • (MyDynamicImplementation, ReturnType, to, ParameterTypeTuple Variant, )
  • , mixin.

, , , URL.

+5

All Articles