digitalmars.D.learn - Get specific functions of unknown type at runtime?
- F i L (37/37) Dec 16 2012 My goal is this, to have an XML file:
- Adam D. Ruppe (33/33) Dec 16 2012 The way I'd do it is to make an interface with a generic call
- F i L (33/33) Dec 16 2012 @Adam D. Ruppe
- Jacob Carlborg (7/37) Dec 17 2012 Don't know if this is what you need, but you could talk a look at:
- Adam D. Ruppe (16/19) Dec 17 2012 Not that I know of, no. Though maybe a templated constructor
- F i L (1/1) Dec 17 2012 Okay, thanks for the help folks.
- Jacob Carlborg (6/42) Dec 16 2012 For the serialization part you could have a look at Orange:
My goal is this, to have an XML file: <!-- scene.xml --> <scene> <object class="Person" event="greet"/> </scene> and a D file: module person; import std.stdio; class Person { void greet() { writeln("hello"); } } and then another D file: module main; import person; import std.xml; import std.file; static class Engine { static void delegate() event; static void callEvent() { event(); } } void main() { auto doc = new Document(read("scene.xml")); auto className = /* find class name in xml file */; auto eventName = /* find event name in xml file */; auto obj = Object.factory(className); Engine.event = /* get 'eventName' void in 'obj' */; for (/* some loop */) { Engine.callEvent(); } } So yeah, basically is is possible to create a general object, then look at it's members at runtime? Through maybe a .classinfo or something? Or is this level of runtime reflection simply not supported in D (yet)? If so, what are my best alternative options here?
Dec 16 2012
The way I'd do it is to make an interface with a generic call method. The classes themselves fill this out using __traits. interface SceneObject { void _callFunction(string name); } mixin template SceneObjectReflection() { override void _callFunction(string name) { foreach(funcname; __traits(derivedMembers, typeof(this))) { static if(funcname[0] != '_') // just to skip stuff like _ctor if(funcname == name) { __traits(getMember, this, funcname)(); return; } } throw new Exception("no such method"); } } class Person : SceneObject { mixin SceneObjectReflection!(); void greet() { writeln("hello"); } } Then you can use it like: void main() { auto obj = cast(SceneObject) Object.factory("test6.Person") ; if(obj is null) throw new Exception("no such class"); obj._callFunction("greet"); } Where of course the class name and the function name are runtime strings. It will still be a bumpy ride to make this work in a real world situation, but this is how I would get started.
Dec 16 2012
Adam D. Ruppe Damn, I was afraid you where going to say to do something like that. It doesn't really work for what I'm thinking about, but thanks for confirming that my original code can't work. I have an alternative in mind, but first, is there a possible way for a Super class to ask about a derivative's members during constructions? (I'm guessing not). Something like: import std.stdio, std.traits; class A { this() { alias typeof(this) type; static if (hasMember!(type, "foo")) { auto top = cast(type) this; top.foo(); } } } class B : A { void foo() { writeln("foobar"); } } void main() { auto b = new B(); // prints: 'foobar' } I assume there's no way (I can't get it to work), but I've heard odd things about 'typeof(this)' before, I just can't remember exactly what, so I figure it's worth asking about. If not, I have an alternative way to accomplish what I want. It's just not as ideal. I really wish D has partial classes, that would be awesome. Jacob Carlborg Thanks for the link.
Dec 16 2012
On 2012-12-17 08:54, F i L wrote:Adam D. Ruppe Damn, I was afraid you where going to say to do something like that. It doesn't really work for what I'm thinking about, but thanks for confirming that my original code can't work. I have an alternative in mind, but first, is there a possible way for a Super class to ask about a derivative's members during constructions? (I'm guessing not). Something like: import std.stdio, std.traits; class A { this() { alias typeof(this) type; static if (hasMember!(type, "foo")) { auto top = cast(type) this; top.foo(); } } } class B : A { void foo() { writeln("foobar"); } } void main() { auto b = new B(); // prints: 'foobar' } I assume there's no way (I can't get it to work), but I've heard odd things about 'typeof(this)' before, I just can't remember exactly what, so I figure it's worth asking about. If not, I have an alternative way to accomplish what I want. It's just not as ideal. I really wish D has partial classes, that would be awesome.Don't know if this is what you need, but you could talk a look at: http://flectioned.kuehne.cn/ It's basically runtime reflection implemented by inspecting the symbol table in the currently running executable. Note that this is old D1 code. -- /Jacob Carlborg
Dec 17 2012
On Monday, 17 December 2012 at 07:54:08 UTC, F i L wrote:I have an alternative in mind, but first, is there a possible way for a Super class to ask about a derivative's members during constructions? (I'm guessing not). Something like:Not that I know of, no. Though maybe a templated constructor could so some magic. class SceneObject { this(T)(T t) { ... } } class Person : SceneObject { this() { super(this); } // calls the templated superclass magic, which will have T == Person } But this isn't that much different than the mixin approach in that you still have to do something special with the child classes. My dmd segfaults when I don't put a constructor in the child class at all... I think there's bug fixes coming in the new dmd about these templated constructors so it might get better. idk.
Dec 17 2012
On 2012-12-17 02:39, F i L wrote:My goal is this, to have an XML file: <!-- scene.xml --> <scene> <object class="Person" event="greet"/> </scene> and a D file: module person; import std.stdio; class Person { void greet() { writeln("hello"); } } and then another D file: module main; import person; import std.xml; import std.file; static class Engine { static void delegate() event; static void callEvent() { event(); } } void main() { auto doc = new Document(read("scene.xml")); auto className = /* find class name in xml file */; auto eventName = /* find event name in xml file */; auto obj = Object.factory(className); Engine.event = /* get 'eventName' void in 'obj' */; for (/* some loop */) { Engine.callEvent(); } } So yeah, basically is is possible to create a general object, then look at it's members at runtime? Through maybe a .classinfo or something? Or is this level of runtime reflection simply not supported in D (yet)? If so, what are my best alternative options here?For the serialization part you could have a look at Orange: https://github.com/jacob-carlborg/orange It won't handle the dynamic methods though. -- /Jacob Carlborg
Dec 16 2012