简体   繁体   中英

Inject object as lazy loading

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);
    }
}

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM