懒惰依赖注射 [英] Lazy Dependency Injection

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

问题描述

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

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

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



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



我的同事建议我使用Factory模式来控制所有的实例,但我不知道IoC有如此优秀的设计错误。



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



任何建议?

解决方案

过早优化:不要这样做。



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



如果创作真的很贵,你通常应该隐藏一个代理后面的创建,而不是注入一个 Lazy< T> ,因为这样允许应用程序忘记了延迟创建的机制(您的应用程序代码和测试代码在执行此操作时变得越来越复杂)。



然而,一个 Lazy< T> 只消耗20个字节的内存(假设一个32位进程)一个 Lazy< T> 实例实际上是免费的。所以没有必要担心这一点,除非你处于内存限制严格的环境中。



如果内存消耗是一个问题,请尝试注册服务一生的时间大于短暂的。您可以按照每个请求,每个网络请求或单例进行。我甚至会说,当您处于创建新对象的环境中时,您应该只能使用单例服务(但是,由于您正在构建一个Web应用程序,因此您不太可能正在处理这样的环境)



请注意,Ninject是.NET的较慢的DI库之一。如果这让您感到困扰,切换到更快的容器。一些容器具有手动接近的新增对象图表的性能。
但一切手段,做个人简介,许多开发人员为了错误的原因切换DI库。



另请注意,使用 Lazy< T> 作为依赖关系是泄漏抽象(这是一个违反依赖性反转原则)。请阅读此答案获取更多信息。


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?

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.

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.

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?

Any suggestions?

解决方案

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

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.

If the creation is really expensive, you should normally hide the creation behind a proxy instead of injecting a Lazy<T>, since this allows the application to be 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).

However, a Lazy<T> just consumes 20 bytes of memory (assuming a 32bit process) and the creation of an 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.

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).

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.

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

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

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