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