懒惰的依赖注入 [英] Lazy Dependency Injection

查看:27
本文介绍了懒惰的依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a project where the Ninject is used as IoC container. My concern is that a lot of classes have such kind of constructors:

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

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

What if I don't want to have all instances of these classes at once?

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

The way, when all this classes are wrapped by Lazy<T> and passed to constructor is not exactly what I need. The T instances are not created yet, but Lazy<T> instances are already stored in memory.

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

My colleague is suggesting me to use Factory pattern to have control over all instantiations, but I'm not sure that IoC have such great design bug.

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

Is there a workaround for this situation or IoC really have such big defect in it's design? Maybe I should use another IoC container?

有什么建议吗?

推荐答案

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

Seems to me that you are doing premature optimization: don't do it.

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

The constructors of your services should do nothing more than storing the dependencies that it takes in private fields. In that case the creation of such an object is really light weight. Don't forget that object creation in .NET is really fast. In most cases, from a performance perspective, it just doesn't matter whether those dependencies get injected or not. Especially when comparing to the amount of objects the rest of your application (and the frameworks you use) are spitting out. The real costs is when you start using web services, databases or the file system (or I/O in general), because they cause a much bigger delay.

如果创建真的很昂贵,您通常应该将创建隐藏在虚拟代理 而不是在每个使用者中注入 Lazy,因为这允许常见的应用程序代码忽略以下事实:存在延迟创建的机制(您的应用程序代码和测试代码都是这样做时会变得更复杂).

If the creation is really expensive, you should normally hide the creation behind a Virtual Proxy instead of injecting a Lazy<T> in every consumer, since this allows common application code to stay oblivious to the fact that there is a mechanism to delay the creation (both your application code and test code are becoming more complex when you do this).

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

Chapter 8 of Dependency Injection: Principle, Practices, Patterns contains a more detailed discussion about lazy and Virtual Proxies.

然而,一个 Lazy 只消耗 20 字节的内存(另一个 24 字节a> 为其封装的 Func,假设为 32 位进程),并且创建 Lazy 实例实际上是免费的.因此无需担心这一点,除非您处于内存限制非常严格的环境中.

However, a Lazy<T> just consumes 20 bytes of memory (and another 24 bytes for its wrapped Func<T>, assuming a 32bit process), and the creation of a Lazy<T> instance is practically free. So there is no need to worry about this, except when you’re in an environment with really tight memory constraints.

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

And if memory consumption is a problem, try registering services with a lifetime that is bigger than transient. You could do a per request, per web request, or singleton. I would even say that when you're in an environment where creating new objects is a problem, you should probably only use singleton services (but it's unlikely that you're working on such an environment, since you're building a web app).

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

Do note that Ninject is one of the slower DI libraries for .NET. If that's troubling you, switch to a faster container. Some containers have performance that is near newing up object graphs by hand. but by all means, do profile this, many developers switch DI libraries for the wrong reasons.

请注意,使用 Lazy 作为依赖项是一种泄漏抽象(违反了依赖倒置原则).请阅读这个答案 了解更多信息.

Do note that the use of Lazy<T> as dependency is a leaky abstraction (a violation of the Dependency Inversion Principle). Please read this answer for more information.

这篇关于懒惰的依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆