喜欢线程问题?瓶颈?记忆问题?
答案 0 :(得分:1)
一个重要的方面是定义正确的对象生命周期(singleton vs prototype
- 永远不知道正确的技术术语是什么)或者你可能会遇到一些讨厌的线程问题。至于瓶颈和内存问题,这些与DI框架无关,或者至少我从来没有任何与DI框架相关的内容。
答案 1 :(得分:1)
这取决于你我们的框架,但总的来说我会说不。您应该在一个线程上配置IoC,然后所有其他线程都从IoC读取。如果您担心瓶颈或内存占用,您可以自己动手,但大多数众所周知的解决方案也没有这些问题。
编辑: 我想我会更新这个以提供更多信息并澄清我的答案。
这是我的观点,但DI容器的主要用途是灵活性和可测试性。从灵活的角度来看,您没有在业务逻辑中引用具体实现。例如,如果您的逻辑中没有DI或某个工厂需要调度服务,则需要执行以下操作:
SchedulingService schedulingService = new SchedulingService();
但是对于DI容器或工厂,你会做类似的事情:
ISchedulingService schedulingService = IoC.GetInstance<ISchedulingService>();
因此,您正在编程为接口或基类而不是具体类型(您正在创建预定义的东西),这意味着您可以在编译时在该服务上注入修改后的版本。这导致了第二点,即可见性。真正好的是,业务逻辑类甚至不会使用它上面的任何一行,只会调用它的方法或属性,就像它已经知道它们一样。实现这一目标的方法是在构造时将依赖项注入对象:
public UpdateDeployment(ISchedulingServer Scheduler)
{
_scheduler = Scheduler;
}
然后可以在测试时嘲笑或伪造。但是在您的业务逻辑中,您可以为业务对象调用重载的默认构造函数,该构造函数从DI容器中获取依赖关系,然后在上面调用该构造函数:
public UpdateDeployment() : this (IoC.GetInstance<ISchedulingService>()) {}
现在说了一遍,从我做过的研究来看,DI容器是一个哈希表,其中有一些逻辑用它来帮助它的配置(实际上它是哈希表的哈希表,但这是一个实现细节)。有关此内容的更多信息和清晰度,请查看CommonServiceLocator project on CodePlex,它定义了所有主要DI容器支持的接口。从这个角度来看,内存占用和周期时间应该很小,但你必须考虑如何使用它。
在我参与过的项目中,我使用过DI容器有两个主要原因。第一个是配置信息。一个例子是连接字符串;我知道你可以将它们放在你的web.config中,但是这限制了你对业务逻辑的测试,因为A)你必须要有整个web堆栈和B)你必须在单元测试和集成测试之间修改文件。在我参与过的项目中,我已经在一个在global.asa中配置的DI容器中注入了连接字符串,这基本上使其成为其他答案中所述的单例。这也适用于引用类型(我知道字符串是引用类型,但很多人使用它们/将它们视为支持值类型),但是您需要确保业务逻辑不会更改其状态。换句话说,它应该只对属性使用getter,或者只应该调用对依赖本身没有任何副作用的方法。
这导致我使用DI提供服务对象的第二个原因。与上面的逻辑一样,SchedulingService是我正在处理的域的逻辑转储。它提供的服务可以操作或提供业务逻辑可以使用的数据,但它不会自行更改。对自身的任何更改都是在构造时处理的,或者由DI容器处理(需要担心引用计数和锁定,这意味着它也不应该这样做)。这将解决任何线程问题,因为从业务逻辑的角度来看,容器内的数据是不可变的。
从ASP应用程序或任何有许多客户端访问它的应用程序使用访问其他依赖项的业务逻辑组件,DI可以帮助处理内存占用空间大小,但它也可能会对其造成伤害。例如,如果我有一个需要在每个请求上实例化的服务(但该服务是不可变的),那么我将使对象X的内存占用数量为并发会话数。但是,如果我有一个很少被调用的服务,我会在应用程序启动时分配内存,而它只是坐在那里等待使用。我已经看到了我工作过的代码中的第一个而不是第二个。
希望有所帮助。
答案 2 :(得分:1)
所有这些都是关注的问题,但无论你是否使用DI,都是如此。
如果您将单例注入对象,确保其共享状态中的任何一个都是线程安全的非常重要。我工作的一个项目在Web层中注入了验证类。有人决定在对象中缓存一个值,而不是每次都回到数据库而不考虑线程安全性。我们遇到了一个问题,即在我们删除了数据成员后,UI中显示了错误的状态。