Runtime reflection/dynamic classloading (was: Re: F# = D + reflection)

Robert Fraser fraserofthenight at gmail.com
Thu Jul 5 14:00:29 PDT 2007


jThe more I look into this, the more I realize that D already has most of the reflection capabilities it needs.

Flectioned: The syntax could be easier to use (not Thomas's fault, D just isn't that flexible with regards to runtime type info), but traced exceptions, etc. make this a VERY viable option. Better Windows support would be nice, but I tend to compile the .map file in as a resource and load it from there, so no harm done. The main problem is that while reflection is possible, introspection (getting the list of methods/fields a class/module has, etc.) is more difficult. It's inability to create a class with an arbitrary constructor is a problem, too.

drefgen/rodin: Haven't used it yet, but this looks like it fixes a lot of the shortcomings of runtime info (Flectioned), but requires that the coder run the tool on their code and compile extra stuff in, which makes it ineffective for generalized reflection on arbitrary code.

DDL: Not technically for reflection, but its dynamic loading facilities are impressive, to say the least, so for plugins, etc., it definitely beats out trying to work around D's DLL incompatibilities. I haven't used it in a while (since the old days when it was Mango-based), but I think Pragma is working on it again, which is great news (since it means my D project is no longer blocked...). For 99% of the uses of dynamic classloading, this is perfect.

As far as relection goes in general, it's somewhat of an anti-pattern in most cases it's used, anyway. See:
 http://www.informit.com/isapi/product_id~%7B7DE69993-3EF5-4354-9E10-9F8A535909F1%7D/content/images/0201310058/samplechapter/blochch7.pdf

Item #35.

My summary of it:
- You lose all the benefits of compile-time type checking
- The code required to perform reflective access is clumsy and verbose (IMO, less so in D than in Java, Flectioned and DDL have pretty interfaces)
- Performance suffers

The main uses are RPC systems, component-based application builder tools, code analysis tools, interpreted embedded systems, etc.

He suggests you use interfaces and only use reflection to instantiate instances of classes, which is totally possible in D:

// Warning: Totally untested
module example;

import object.ClassInfo;
import tango.io.Stdout;

interface IFriendlyPerson
{
    void sayHello();
}

class Fraser : IFriendlyPerson
{
    void sayHello()
    {
        Stdout("Why hello there, world!");
    }
}

void main()
{
    IFriendlyPerson me = cast(IFriendlyPerson) ClassInfo.find("example.Fraser").create();
    me.sayHello();
}

While I think better language support for reflection is a good idea, I'm starting to think it's probably less important than:
- Fixing/working more with const stuff
- Struct constructors
- Macro syntax
(All which are supposedly in the works right now), and anything else coming in the 2.0 branch.



More information about the Digitalmars-d mailing list