Interceptors

Sometimes, you need to add certain behavior to objects that activates once they have been created. Or perhaps you want to log object creation. One common example is an interceptor that runs a method on an object in a new thread. Let's look at the necessary code to implement that.

Custom logic

First, we want to start with an interface that marks the type as being runnable:

interface IThreadRunnable
{
    void run();
}

And the code that will run one of these:

void run (IThreadRunnable runnable)
{
    new Thread(&runnable.run).start();
}

Writing the interceptor

The interceptor class is simple. It must have a default constructor and a method void intercept(T)(T object):

class ThreadRunnableInterceptor
{
    void intercept (T) (T object)
    {
        // Any code you want here -- in this case, we run the object if it's
        // runnable.
        static if (is (T : IThreadRunnable))
        {
            run (object);
        }
    }
}

Using the interceptor

All we have to do now is add that to our own Builder. The process is somewhat annoying, but not difficult or verbose:

module mypackage.builder;
public import dconstructor.api;

private Builder!(ThreadRunnableInterceptor) _builder;
public typeof(_builder) builder ()
{
    if (_builder is null)
    {
        _builder = new typeof(_builder)();
    }
    return _builder;
}

Now just have your modules import mypackage.builder rather than dconstructor.default_builder, and it will work.

For reference, you can look at the examples, specifically interceptor.d in the examples folder (dconstructor/trunk/dconstructor/examples).