Reputation: 12053
I have MVC code like below. I use nInject for IoC.
I wonder when I push request to do for example SendMail there is create controller object, nInject create subobjects for both readonly objects: _mailSrv and _dbSrv, but I need in this request only one variable.
Is it possible to inject variable as lazy loading. When code will need object, then it will be created?
public class HomeController:Controller
{
private readonly IMailService _mailSrv;
private readonly IDatabaseService _dbSrv;
public HomeController:Controller(IMailService mailSrv, IDatabaseService dbSrv)
{
_mailSrv = mailSrv;
_dbSrv = dbSrv;
}
public ActionResult SendMail(string mailAddress)
{
_mailSrv.Do(mailAddress);
}
public ActionResult SaveToDatabase(int id, string data)
{
_dbSrv.Do(id, data);
}
}
Upvotes: 4
Views: 599
Reputation: 1116
Just tried it out.
Add Ninject.Extensions.Factory to your project and change the member variables to Lazy.
public class HomeController : Controller
{
private readonly Lazy<IMailService> _mailSrv;
private readonly Lazy<IDatabaseService> _dbSrv;
public HomeController(Lazy<IMailService> mailSrv, Lazy<IDatabaseService> dbSrv)
{
_mailSrv = mailSrv;
_dbSrv = dbSrv;
}
public ActionResult SendMail(string mailAddress)
{
_mailSrv.Value.Do(mailAddress);
}
public ActionResult SaveToDatabase(int id, string data)
{
_dbSrv.Value.Do(id, data);
}
}
Instances will now be created lazily.
Upvotes: 5
Reputation: 1285
Hmm, Not sure about ninject in particular, but normally no, you would get instances of the objects when the controller is instantiated.
Alternatives would be:
Make two controllers (I suggest this one)
Inject factories rather than objects
Personally this is not for me, I think the IoC container should be your factory.
public ActionResult SendMail(string mailAddress)
{
_mailSrvFactory.Create().Do(mailAddress);
}
Directly bind the object in the method rather than injecting
This is usually considered 'bad' because you have to pass the IoC container around
public ActionResult SendMail(string mailAddress)
{
kernel.Get<IMailServer>().Do(mailAddress);
}
I guess looking at it at a deeper level, It might be possible to create a custom scope which in effect wrapped the class in a factory in the same way that IoC containers can provide classes as singletons. I'd have to think about that one though
Upvotes: 2