January 10, 2008
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.