Lazy binding with Ninject

1 Comment November 23, 2012

There may well be a much more elegant way of achieving the same goal, but this is what I’ve come up with.

Now, I know that I will probably be denounced by those with far better Inversion of Control skills than I as some sort of heretic, but there are times when I need inject dependencies into a class with constructor injection but not have the dependency resolved until it’s actually accessed – an intent to use an injected dependency if you will.

public class LazyBinding : NinjectModule
{
    public override void Load()
    {
        Bind(typeof (Lazy<>))
            .ToMethod(
                context =>
                ((ILazyLoader) Activator.CreateInstance(typeof (LazyLoader<>).MakeGenericType(context.GenericArguments),
                                                        new object[] { context.Kernel })).Loader);
    }

public interface ILazyLoader
{
    object Loader { get; }
}

public class LazyLoader&lt;T&gt; : ILazyLoader
{
    private readonly IKernel _kernel;
    private static readonly Func&lt;IKernel, Lazy&lt;T&gt;&gt; _lazyLoader = k =&gt; new Lazy&lt;T&gt;(() =&gt; k.Get&lt;T&gt;());

    public LazyLoader(IKernel kernel)
    {
        if (kernel == null)
            throw new ArgumentNullException("kernel");

        _kernel = kernel;
    }

    public object Loader { get { return _lazyLoader(_kernel); } }
}

}

After loading the LazyBinding module into the Ninject kernel, it is possible to inject a lazily-loaded type in the following fashion:

public class Foo
{
    private readonly Lazy<IBar> _lazyBar;

    public Foo(Lazy<IBar> lazyBar)
    {
        if (lazyBar == null)
            throw new ArgumentNullException("lazyBar");

        _lazyBar = lazyBar;
    }

    public IBar Bar { get { return _lazyBar.Value; } }
}

1 Comment

  • Gravatar Image
    edcourtenay February 3, 2013 11:28 AM

    Of course, if I'd bothered to look I would've found that the Ninject.Extensions.Factory package already provided this functionality!

    https://github.com/ninject/ninject.extensions.factory/wiki