将对象注入延迟加载

时间:2015-04-24 13:58:27

标签: c# .net model-view-controller ninject inversion-of-control

我有如下的MVC代码。我使用nInject for IoC。 我想知道当我推送请求时,例如 SendMail 有创建控制器对象,nInject为两个只读对象创建子对象: _mailSrv _dbSrv ,但我在此请求中只需要一个变量。

是否可以将变量注入延迟加载。当代码需要对象时,它会被创建吗?

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

2 个答案:

答案 0 :(得分:5)

试了一下。

Ninject.Extensions.Factory添加到项目中,并将成员变量更改为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);            
    }
}

现在将懒惰地创建实例。

答案 1 :(得分:2)

嗯,特别是对ninject不确定,但通常不会,在实例化控制器时会得到对象的实例。

替代方案是:

制作两个控制器(我建议这个)

注入工厂而不是对象

就我个人而言,我认为IoC容器应该是您的工厂。

public ActionResult SendMail(string mailAddress)
    {
        _mailSrvFactory.Create().Do(mailAddress);
    }

直接绑定方法中的对象而不是注入

这通常被视为“不好”。因为你必须传递IoC容器

public ActionResult SendMail(string mailAddress)
    {
        kernel.Get<IMailServer>().Do(mailAddress);
    }

我想在更深层次上看一下,有可能创建一个自定义范围,它实际上将类包装在工厂中的方式与IoC容器可以提供类作为单例的方式相同。我不得不考虑那个