Ninject: Auto-registration is changing in version 3

When I was using Ninject v2.2 I had this code to do my auto-registration:

using Ninject;
using Ninject.Extensions.Conventions;

public class CommonBootstrapper<TShell>
{
    private StandardKernel _kernel;

    protected override void Configure()
    {
        _kernel = new StandardKernel();
        _kernel.Scan(scanner =>
                         {
                             scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
                             scanner.BindWithDefaultConventions();
                             scanner.InSingletonScope();
                         });
    }
}

For various reasons I upgraded to Ninject v3.0 RC3, and I found that there have been a number of breaking in Ninject.Extensions.Conventions.  My code now looks like this:

using Ninject;
using Ninject.Extensions.Conventions;

public class CommonBootstrapper<TShell>
{
    private StandardKernel _kernel;

    protected override void Configure()
    {
        _kernel = new StandardKernel();
        _kernel.Bind(scanner => scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
                                    .Select(IsServiceType)
                                    .BindToDefaultInterface()
                                    .Configure(binding => binding.InSingletonScope()));
    }

    private static bool IsServiceType(Type type)
    {
        return type.IsClass && type.GetInterfaces().Any(intface => intface.Name == "I" + type.Name);
    }
}

 

So there is a sweet new fluent interface, but more importantly you have to specify the exact conventions to use.  This makes it a lot easier to have non-standard convention, but it would be great if Ninject had the standard convention built in (IFoo binds to Foo).

For those who are into their own custom binding conventions (like Anthony), you will unfortunately find that the IBindingGenerator interface has changed.  Here is the v2.2 way of implementing a custom binding:

public class ViewModelConventions : IBindingGenerator
{
    public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)
    {
        if(type != null && kernel != null && !type.IsAbstract && type.IsClass && type.Name.EndsWith("Model"))
        {
            kernel.Bind(type)
                  .ToSelf()
                  .InScope(scopeCallback);
        }
    }
}

And here is the same class ported to Ninject v3.0 RC3.

public class ViewModelConventions : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        if (type != null && !type.IsAbstract && type.IsClass && type.Name.EndsWith("Model"))
        {
            yield return bindingRoot.Bind(type)
                                    .ToSelf();
        }
    }
}

It must be said, however, the goodness of the new fluent interface shown above means that I no longer need a custom binding generator – instead I can simply select the types I want and bind them directly in my bootstrapper.   I suspect that others will find the same!

March 20 2012

Pingbacks and trackbacks (1)+

Comments are closed