惰性dependency injection

我有一个项目,其中Ninject用作IoC容器。 我担心的是很多类都有这样的构造函数:

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

如果我不想同时拥有这些类的所有实例怎么办?

当所有这些类被Lazy包装并传递给构造函数的方式并不是我所需要的。 尚未创建T实例,但Lazy实例已存储在内存中。

我的同事建议我使用Factory模式控制所有实例,但我不确定IoC是否有这么好的设计错误。

有没有针对这种情况的解决方法,或者IoC在其设计中确实存在如此大的缺陷? 也许我应该使用另一个IoC容器?

有什么建议?

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

您的服务的构造函数除了存储它在私有字段中所使用的依赖项之外,不应该做什么。 在这种情况下,创建这样的对象实际上是轻量级的。 不要忘记.NET中的对象创建速度非常快。 在大多数情况下,从性能角度来看,这些依赖关系是否被注入并不重要。 特别是在与对象数量进行比较时,应用程序的其余部分(以及您使用的框架)正在吐出。 实际成本是当您开始使用Web服务,数据库或文件系统(或一般的I / O)时,因为它们会导致更大的延迟。

如果创建非常昂贵,通常应该隐藏虚拟代理后面的创建,而不是在每个消费者中注入一个Lazy ,因为这允许常见的应用程序代码无法忽略这样一个事实:有一种机制可以延迟创建(当你这样做时,你的应用程序代码和测试代码都变得越来越复杂)。

.NET中的dependency injection的第6章,第二版包含有关延迟和虚拟代理的更详细讨论。

但是, Lazy只消耗20个字节的内存(假设32位进程,其包装的Func还有24个字节 ),并且创建一个Lazy实例几乎是免费的。 所以没有必要担心这一点,除非你在一个内存严重受限的环境中。

如果内存消耗是一个问题,请尝试注册寿命大于瞬态的服务。 您可以针对每个Web请求或单个请求执行每个请求。 我甚至会说,当你在一个创建新对象的环境中出现问题时,你应该只使用单一服务(但是你不太可能在这样的环境中工作,因为你正在构建一个web应用程序) 。

请注意,Ninject是.NET中较慢的DI库之一。 如果那令您不安,请切换到更快的容器 。 一些容器的性能接近于手动创建对象图。 但是,无论如何,要对此进行分析,许多开发人员出于错误的原因切换DI库。

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

史蒂文说这看起来像过早的优化是正确的。 这些物体的构造非常快,通常不会成为瓶颈。

但是,使用Lazy来表达依赖项,您不需要立即使用它是dependency injection框架中的常见模式。 Actofac就是这样一种容器,它内置了对各种包装类型的支持。 我相信Ninject也有一个扩展,也许看看这个, Ninject Lazy 。