www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting object members

reply "Szymon Gatner" <noemail gmail.com> writes:
Hi,

I am trying to get members of a class via pointer to Object.

I know how to iterate over members when type is known at compile 
time (with __traits) but I can't find a documentation of how to 
get them polymorphically, I mean:

class Foo
{
   int x, y;
}

Object o = new Foo();
auto ci = o.classinfo;

// what to do now to get members?

I found a solution that called getMembers() on ci object but I am 
getting compilation error when trying to call it. I would also 
like to be able to check access level of members as with 
__traits().

Also: Is there any article / tutorial on D's introspection 
capabilities. I heard it is pretty powerful and I would really 
like to try it.

Regards,
Szymon
Jun 12 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 12 June 2013 at 10:59:42 UTC, Szymon Gatner wrote:
 I know how to iterate over members when type is known at 
 compile time (with __traits) but I can't find a documentation 
 of how to get them polymorphically, I mean:
It hasn't been implemented in the runtime yet (though all the pieces are there), so unless each class makes the info available itself (or you want to modify your runtime) you can't. For example: claas Foo { int x, y; mixin ReflectionInfo!Foo; } Where ReflectionInfo is something you'd write. Jacob Carlborg has written a serialization library that works like this: https://github.com/jacob-carlborg/orange But even so it wouldn't work through Object or classinfo unless you modify druntime. I'd like to see some functionality for this in for the next release (or maybe the one after it) though.
 Also: Is there any article / tutorial on D's introspection 
 capabilities. I heard it is pretty powerful and I would really 
 like to try it.
I don't think so. The basic idea though is: foreach(member; __traits(allMembers, SomeClass)) { // member is a string, the name of the member // get the thing like this: __traits(getMember, SomeClass, member) } Then you look into it with the other traits and use std.traits from the stdlib for helper functions.
Jun 12 2013
parent "Szymon Gatner" <noemail gmail.com> writes:
Thanks a lot Adam, this is what I came with:

module main;

import std.stdio;

class MyObject
{
   abstract string[] getPublicMembers();
}

class MyClassBase(T) : MyObject
{
   override string[] getPublicMembers()
   {
     return generatePublicMembers!T();
   }

   string[] generatePublicMembers(T)()
   {
     string[] ret;
     foreach(mem; __traits(derivedMembers, T))
     {
       static if (is(typeof(__traits(getMember, T.init, mem))))
       {
         enum prot = __traits(getProtection, __traits(getMember, 
T.init, mem));
         static if (prot == "public")
         {
           ret ~= mem;
         }
       }
     }
     return ret;
   }
}


class Foo : MyClassBase!Foo
{
   public int x;
   protected int y;
   private int p;
}

class Bar : MyClassBase!Bar
{
   int x, y;
   private int p;
}

int main(string[] argv)
{
   MyObject f = new Foo();
   MyObject b = new Bar();

   auto members = f.getPublicMembers();

   foreach (mem; members)
   {
     writeln(mem);
   }

   return 0;
}

what do you think? A question: can a mixin method be an override 
or abstract method?
Jun 13 2013