20

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

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

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

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

我的同事建议我使用工厂模式来控制所有实例化,但我不确定 IoC 是否有如此出色的设计错误。

这种情况是否有解决方法,或者 IoC 的设计真的有这么大的缺陷?也许我应该使用另一个 IoC 容器?

有什么建议么?

4

3 回答 3

50

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

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

如果创建真的很昂贵,您通常应该将创建隐藏在虚拟代理后面,而不是在每个消费者中注入 a Lazy<T>,因为这允许常见的应用程序代码忽略存在延迟创建的机制这一事实(您的应用程序执行此操作时,代码和测试代码会变得更加复杂)。

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

但是, aLazy<T>只消耗 20 字节的内存(假设是 32 位进程,另外24 字节用于它的 Wrapped Func<T>),并且Lazy<T>实例的创建实际上是免费的。因此,无需担心这一点,除非您处于内存限制非常严格的环境中。

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

请注意,Ninject 是 .NET 中速度较慢的 DI 库之一。如果这让您感到困扰,请切换到更快的容器。一些容器的性能接近于手动更新对象图。但无论如何,请对此进行分析,许多开发人员出于错误的原因切换 DI 库。

请注意,使用Lazy<T>as 依赖是一种泄漏抽象(违反依赖倒置原则)。请阅读此答案以获取更多信息。

于 2012-09-05T16:01:43.100 回答
2

Steven 说这看起来像是过早的优化是正确的。这些对象的构建速度非常快,通常不会成为瓶颈。

然而,使用 Lazy 来表达你不需要的依赖是依赖注入框架中的常见模式。Actofac就是这样一种容器,它内置了对各种包装类型的支持。我敢肯定 Ninject 也有一个扩展,也许看看这个Ninject Lazy

于 2014-09-11T22:58:37.153 回答
1

您还可以使用以下语法注入操作方法。(我不确定这到底是什么版本)。

构造函数是最佳实践,但是当我有一个服务正在做一些昂贵的初始化时,我不得不故意这样做一次——事实上是偶然的——但它有一段时间没有被发现,而将它移到一个方法中是最简单的那确实需要它。

如果您只需要从一种操作方法访问服务,这可以使代码更清晰 - 但请记住,如果您将其注入到方法中,您将不得不到处传递它,因为它不再是 on 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

于 2019-01-27T08:20:01.267 回答