懒惰依赖注入(Lazy Dependency Injection)

2019-06-27 20:23发布

我有在Ninject作为IoC容器的项目。 我担心的是,很多班级有这样那样的构造函数:

[Inject]
public HomeController(
    UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) {
   _userManager = userManager;
   _roleManager = roleManager;
   _blahblahManager = blahblahManager;
}

如果我不想要什么有这些类的所有实例一次?

顺便说一下,当所有这些课程都是由缠Lazy<T>并传递给构造不正是我需要的。 的T实例尚未创建的,但Lazy<T>实例已经存储在存储器中。

我的同事是在暗示我使用工厂模式有超过所有实例的控制,但我不知道国际奥委会有这样伟大的设计错误。

是否有这种情况或国际奥委会真的有这么大的缺陷是设计一个解决方法吗? 也许我应该用另一种IoC容器?

有什么建议?

Answer 1:

在我看来,你正在做过早的优化 :不这样做。

您的服务的构造应该做的无非不是存储,它需要在私人领域的依赖关系。 在这种情况下这样的对象的创建是真的重量轻。 不要忘记在.NET那个对象的创建是非常快。 在大多数情况下,从性能的角度来看,它只是无关紧要的依赖关系是否得到注入与否。 尤其是比较对象数量的应用程序(和你使用的框架)的其余部分时吐出。 真正的成本是当你开始使用Web服务,数据库或文件系统(一般或I / O),因为它们会引起更大的延迟。

如果创作真的很贵,你通常应该隐藏背后的创建虚拟代理 ,而不是注入Lazy<T>在每一个消费者,因为这可以让普通的应用程序代码留无视这样的事实,有推迟建立一个机制(均为当你这样做你的应用程序代码和测试代码变得更加复杂)。

第8章依赖注入:原理,实践模式包含了懒惰和虚拟代理更详细的讨论。

然而, Lazy<T>只是消耗20个字节的存储器(和另一个24个字节用于其包裹Func<T>假设32位处理),和一个的创建Lazy<T>实例是实际上不含。 所以没有必要担心这一点,当你在与紧实内存限制的环境中时除外。

如果内存消耗问题,请尝试用一生比短暂的更大注册服务。 你可以做一个每个请求,每个web请求,或单。 我甚至可以说,当你在一个环境中创建新的对象是一个问题,你应该只使用单服务(但它是不可能的,你在这样的环境中工作,因为你正在构建一个Web应用程序) 。

请注意,Ninject是.NET较慢DI图书馆之一。 如果这是困扰你, 切换到更快的容器 。 一些容器有表现就是近用手newing了对象图。 但通过各种手段,做资料这个,很多开发商开关DI库错误的原因。

请注意,使用的Lazy<T>作为依赖性是泄漏的抽象 (违反的依赖性倒置原则 )。 请阅读这个答案以获取更多信息。



Answer 2:

您也可以注入到与下面的语法的操作方法。 (我不太确定这是什么引进版)。

构造函数是最好的做法,但我不得不这样做一次故意的时候我有做一些昂贵的初始化服务-意外事实上-但它不是发现了一会儿,这只是最简单的将它移动到一个方法这确实需要它。

这可以使干净的代码,如果你只需要从一个操作方法访问服务-但是记住如果你把它注入到你必须通过它到处,因为它不再是对法this 。 绝对不要去分配给this.service中的操作方法-这太可怕了。

public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = "Currently on the server the time is " + dateTime.Now;

    return View();
}

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2#action-injection-with-fromservices



Answer 3:

史蒂芬是说,这看起来像过早的优化是正确的。 这些对象的建设是非常快的,通常是从来没有的瓶颈。

然而,使用懒来表达你不需要马上的依赖是依赖注入框架的通用模式。 Actofac是已经内置支持一个这样的容器不同包装类型 。 我敢肯定,也有对Ninject的延伸,以及,也许看看这个, Ninject懒惰 。



文章来源: Lazy Dependency Injection