Lazy loading using Ninject
In my previous blog post I demonstrated how you can use Ninject in your Silverlight application to automatically inject dependencies and make live easier. In the sample I injected the dependency, the PingService, inside my PageModel constructor. That worked just fine because the PingService is lightweight and stateless. However suppose creation is much more involved and you don’t need it all the time so you really want to divert creation until you really need the PingService. Well we can by just a few simple changes.
Changing the PageModel to defer loading of the PingService
This is actually a very easy change. All we need to do is change to constructor from expecting a PingService to expecting a IKernel. The IKernel is the Ninject main object and Ninject will take care of injecting itself. Kind of cool as the Page, which creates and uses the PageModel , doesn’t even need to be aware of the change, Ninject will do all the work here
.
Now we can change the ExecutePing() function to use the kernel to create the PingService when needed and we are done. The new PageModel looks like this:
using System;
using System.ComponentModel;
using System.Threading;
using Ninject.Core;
namespace NinjectSample
{
public class PageModel : INotifyPropertyChanged
{
public PageModel(IKernel kernel)
{
_kernel = kernel;
_context = SynchronizationContext.Current;
}
private IKernel _kernel;
private SynchronizationContext _context;
public DateTime TheResult { get; set; }
public void ExecutePing()
{
PingService.PingService proxy = _kernel.Get<PingService.PingService>();
proxy.BeginPing(proxy_PingCompleted, proxy);
}
void proxy_PingCompleted(IAsyncResult result)
{
PingService.PingService proxy = (PingService.PingService)result.AsyncState;
_context.Post(state =>
{
TheResult = proxy.EndPing(result);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TheResult"));
}, null);
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
The normal generated WCF PingService will work just fine as will the Page, no changes there. The only other change we need to make is to the TestPingService as this was a very simple implementation before. Not that it is very complicated now but it needs to work with a dummy IAsyncResult. The complete fake code looks like this:
using System;
namespace NinjectSample
{
public class TestPingService : PingService.PingService
{
public IAsyncResult BeginPing(AsyncCallback callback, object asyncState)
{
TestAsyncResult result = new TestAsyncResult() { AsyncState = asyncState };
callback(result);
return result;
}
public DateTime EndPing(IAsyncResult result)
{
// Birthdate Charles Babbage
return new DateTime(1791, 12, 26);
}
}
class TestAsyncResult : IAsyncResult
{
public object AsyncState { get; set; }
public System.Threading.WaitHandle AsyncWaitHandle { get; set; }
public bool CompletedSynchronously { get; set; }
public bool IsCompleted { get; set; }
}
}
Easy right 
Conclusion
Even though we are now using lazy loading instead of eager loading Ninject still makes live easy for us.
Enjoy!