我正在尝试为Rails ActionDispatch路由器创建一个类似的路由器,它允许您定义类似的路由
map.get "/foo", :controller => "Foo", :action => "index"
Run Code Online (Sandbox Code Playgroud)
然后将路由GET /foo到FooController#index.有了这个结构,你可以使用像
map.resources :foos
Run Code Online (Sandbox Code Playgroud)
这将调用像
map.get "/foo", :controller => "Foo", :action => "index"
map.get "/foo/:id", :controller => "Foo", :action => "show"
Run Code Online (Sandbox Code Playgroud)
等等.
在D中,我已经能够找出使这项工作所需的许多反身代码,但不是全部.在Ruby中我可以做到:
class Foo
def bar
"FOOO BAR!"
end
end
f = Object.const_get("Foo")
f.new.__send__(:bar) #=> "FOOO BAR!"
Run Code Online (Sandbox Code Playgroud)
我试图翻译成
module foo;
import std.stdio;
class Foo {
void bar() {
writeln("FOO BAR!");
}
}
void main() {
auto foo = Object.factory("foo.Foo");
__traits(getMember, foo, "bar");
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为编译器不知道什么类型foo,所以#bar在编译期间调用失败.我见过的所有地方都Object.factory将它们投射到特定类型,所以
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");
}
Run Code Online (Sandbox Code Playgroud)
会工作得很好.但是,如果我知道我想把对象强加给什么好用的东西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");
}
Run Code Online (Sandbox Code Playgroud)
更新对于现在遇到此问题的任何人,您可以在此处查看我的最终解决方案:https://github.com/jaredonline/action-pack
我这样做的方法是建立自己的工厂功能和动态调度.使用__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", ...]);
Run Code Online (Sandbox Code Playgroud)
我用完整的示例更新了此链接,如果您没有module dynamicstuff;在顶部看到,请刷新:
http://arsdnet.net/dcode/test46.d
循环allMembers,根据运行时字符串调用.通过循环ModuleInfo,获取实现接口的所有类的列表也是可能的.请参阅示例文件的底部以获取执行此操作的功能.
我的web.d这样做是为了从网上自动调用功能.冗长,凌乱的代码,但它做了很多.这是包装函数:https: //github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/web.d#L2538
请注意std.traits中ParameterTypeTuple!func的使用.
我在这里写了很多评论http://arsdnet.net/dcode/test46.d所以希望他们能回答你的问题.该示例简要说明:
你不一定要使用所有这些东西,但我想我会触及所有这些,因为这些对于这些url路由任务都非常有用.
| 归档时间: |
|
| 查看次数: |
471 次 |
| 最近记录: |