Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Update:</strong> My original answer was written before the .NET Framework 4 was released (along with <code>Lazy&lt;T&gt;</code>), and the other answer, while slightly more up-to-date, is still a bit obsolete now. I'm leaving my original answer below in case anybody is stuck on an older version, but wouldn't advise its use with the latest version of Ninject or .NET.</p> <p>The Ninject <a href="https://github.com/ninject/ninject.extensions.factory" rel="nofollow noreferrer">Factory Extension</a> is the modern way of doing this. It will automatically wire up any arguments or properties. You don't need a separate binding for this - just set up your services in the usual way and the extension handles the rest.</p> <p>FYI, the same extension can also wire up custom factory interfaces, or <code>Func&lt;T&gt;</code> arguments. The difference with these is that they'll create a new instance every time, so it's actually a factory, not just lazy instantiation. Just pointing this because the documentation isn't totally clear about it.</p> <hr> <p>As a rule, "complete construction of an object graph" shouldn't be that expensive, and if a class is being injected with dependencies that it may not use, it's probably a good sign that the class has too many responsibilities.</p> <p>This isn't really a limitation of Ninject per se - if you think about it, it's not really possible to have a "lazy dependency" unless either (a) the dependency being injected is itself a lazy loader, such as the <a href="http://msdn.microsoft.com/en-us/library/dd642331(VS.100).aspx" rel="nofollow noreferrer"><code>Lazy&lt;T&gt;</code></a> class in .NET 4, or (b) all of the dependency's properties and methods use lazy instantiation. <em>Something</em> has to be injected in there.</p> <p>You could accomplish (a) relatively easily by using <del>the provider interface</del> a method binding <em>(ed: Ninject doesn't support open generics with provider bindings)</em> and binding an open generic type. Assuming you don't have .NET 4, you would have to create the interface and implementation yourself:</p> <pre><code>public interface ILazy&lt;T&gt; { T Value { get; } } public class LazyLoader&lt;T&gt; : ILazy&lt;T&gt; { private bool isLoaded = false; private T instance; private Func&lt;T&gt; loader; public LazyLoader(Func&lt;T&gt; loader) { if (loader == null) throw new ArgumentNullException("loader"); this.loader = loader; } public T Value { get { if (!isLoaded) { instance = loader(); isLoaded = true; } return instance; } } } </code></pre> <p>Then you can bind the entire lazy interface - so just bind the interfaces as normal:</p> <pre><code>Bind&lt;ISomeService&gt;().To&lt;SomeService&gt;(); Bind&lt;IOtherService&gt;().To&lt;OtherService&gt;(); </code></pre> <p>And bind the lazy interface using open generics to a lambda method:</p> <pre><code>Bind(typeof(ILazy&lt;&gt;)).ToMethod(ctx =&gt; { var targetType = typeof(LazyLoader&lt;&gt;).MakeGenericType(ctx.GenericArguments); return ctx.Kernel.Get(targetType); }); </code></pre> <p>After that, you can introduce lazy dependency arguments/properties:</p> <pre><code>public class MyClass { [Inject] public MyClass(ILazy&lt;ISomeService&gt; lazyService) { ... } } </code></pre> <p>This won't make the <em>entire</em> operation lazy - Ninject will still have to actually create an instance of the <code>LazyLoader</code>, but any <em>second-level</em> dependencies of <code>ISomeService</code> won't be loaded until <code>MyClass</code> checks the <code>Value</code> of that <code>lazyService</code>.</p> <p>The obvious downside is that <code>ILazy&lt;T&gt;</code> does not implement <code>T</code> itself, so <code>MyClass</code> has to actually be written to accept lazy dependencies if you want the benefit of lazy loading. Nevertheless, if it's extremely expensive to create some particular dependency, this would be a good option. I'm pretty sure you'll have this issue with <em>any</em> form of DI, any library.</p> <hr> <p>As far as I know, the only way to do (b) without writing mountains of code would be to use a proxy generator like <a href="http://www.castleproject.org/dynamicproxy/index.html" rel="nofollow noreferrer">Castle DynamicProxy</a>, or register a dynamic interceptor using the <a href="http://github.com/idavis/ninject.extensions.interception" rel="nofollow noreferrer">Ninject Interception Extension</a>. This would be pretty complicated and I don't think you'd want to go this route unless you have to.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload