www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Distributed configuration solution?

Hi all,

I have a tiny, 90% complete dependency injection framework. As it 
stands, it's head and shoulders above Microsoft's CAB framework (though 
that's not hard). It avoids any order requirements in configuration, 
which is the main advantage, and it even handles literals (strings and 
other builtin types), special cases (injecting one thing while building 
one type and a different when building a different type), arrays, and 
associative arrays.

There's one glaring problem. Configuration. How to associate an 
implementation with an interface or abstract class.

Currently, you can do this manually:
builder.bind!(IInterface, ClassImplementing);

This is ugly.
You put all the configuration in one place -- which is, I guess, a good 
thing. But you keep the configuration for a given class/interface pair 
far from the class and far from the interface. That is a bad thing. It's 
a noticeable source of bloat. I don't want one of these giant 1000-line 
module files like I've seen with CAB.

I want some means of registering implementations closer to the 
implementations. But my code knows nothing about the implementations 
unless it's told. It only has access to the interface.

1. My first idea was to fake C# attributes / Java annotations using 
templated interfaces:

interface ImplementedBy(T) {}

interface UserInterface : ImplementedBy!(Implementation) {
//...
}

Then my code goes:
static if (is (TToBuild : ImplementedBy!(U), U)) {
    return build!(U);
}

That's supposed to work, but it doesn't.

2. My next thought was a static constructor:
class Implementation : UserInterface {
    static this () {
       builder.bind!(UserInterface, typeof(this));
    }
}

This is ugly.

3. Then I thought, combine the two:

abstract class Implements(T) {
    static this () {
       builder.bind!(UserInterface, ???? FAIL);
    }
}

If I solved the template problem:
class Implementation : BaseImplementation, UserInterface {}

4. This leaves a mixin, which is only slightly ugly:
template Implements(T) {
    // typeof(this) works here
    return `static this () { builder.bind!(` ~ T.stringof ~ `, 
typeof(this); }`;
}

class Implementation {
    mixin(Implements!(UserInterface));
}

This seems to be best, but does anyone have a better suggestion?

I just hate that D forces these mixins plus static services rather than 
having a decent way to provide metadata.
Jan 09 2008