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<T> : ILazyLoader { private readonly IKernel _kernel; private static readonly Func<IKernel, Lazy<T>> _lazyLoader = k => new Lazy<T>(() => k.Get<T>()); 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; } } }
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