Reflection

Bruno Medeiros daiphoenixNO at SPAMlycos.com
Thu Mar 2 06:38:53 PST 2006


Ok, I know many people have asked about reflection before, and surely 
everyone agrees it's a useful feature.
So what I want to know is what are the issues and challenges to design 
and implement such feature? Because now that I think of it, it seems to 
me it would be quite easy to implement runtime reflection, at least for 
field members of class objects. (method members have some problems, 
because of D's limited type information about function types)

So let's see, what do we need for reflection? We need to be able to 
determine the class of an anonymous object (already done with RTTI). And 
we need to be able do determine and access the field members of such 
object. That could be done, I believe, with a list of each field's type 
and offset relative to the object reference (this pointer).
Since we already have a TypeInfo structure, this could be done easily. 
Imagine that the ClassInfo class, has two additional members:
   TypeInfo[] memberids;
an array of the TypeInfo of each field of the class.
   int[] memberoffsets;
a respective array of the offsets relative to the 'this' pointer where 
the member is located. (should actually be size_t[] or something)

So now with this one can use reflection on an object, similarly to how 
one reads argument info from a variadic function with TypeInfo (which is 
where I got my idea). Here's a raw example of usage of such feature, a 
generic object serialization(writing to disk or somewhere else) function:


// Runtime reflection
void serialize(Object obj)
{
   TypeInfo[] memberids = obj.classinfo.memberids;
   int[] memberoffsets = obj.classinfo.memberoffsets;

   writefln(memberids.length, " members");

   foreach(int ix, TypeInfo memberid; memberids)
   {
     if (memberid == typeid(int)) {
       int m = * cast(int*) (cast(byte*)obj + memberoffsets[ix]);
       // Note that the previous could be abbreviate with something like:
       // int m = * obj.getMember!(ix, int);
       writefln("Member ",ix,", type int, value: ", m);
     }
     else if (memberid == typeid(char)) {
       char m = * cast(char*) (cast(byte*)obj + memberoffsets[ix]);
       writefln("Member ",ix,", type char, value: ", m);
     }
     // ... etc. for long, unsigneds and other primitive types

     else if (memberid.isClass()) {
       Object m = cast(Object) (cast(byte*)obj + memberoffsets[ix]);
       serialize(m);
     }
   }
}


Ok, this shows the usefulness of such feature, however there are some 
problems/limitations. It only works with primitive types (there is no 
isClass method of TypeInfo). For this feature to reach the full 
potential, then the TypeInfo class would have to be extended with info 
about the type's type, (i.e., the metatype, like struct, class, 
function, primitive, etc.), so that one could use reflection with 
non-primitive types, especially classes and arrays.

None of this seems to be hard or long to implement, so how about it? (I 
know many details need to be fleshed out, but the base idea seems good)

-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to 
be... unnatural."



More information about the Digitalmars-d mailing list