我认为这部分是对先前答案的一些评论的重新整理,但我试图举例说明对一些推理的扩展。
一旦进入管理注入对象生命周期的领域,您可能应该为这些对象创建工厂。
根本问题是组合根不知道创建对象所需的调用环境上下文是什么。
我想我应该退后一步,在这一点上解释一下。
关于依赖注入的公认智慧是在代码入口点附近有一个组合根。这有很多很好的理由,在网上不难找到,所以我不会在这里讨论。
组合根是您将接口(通常但可能是对象)映射到它们的实现的地方。您可以将此时可用的信息传递给构造函数。因此,您可以传入一个对象的引用,该对象的生命周期在执行组合根时是当前的。
但是,如果组合根的生命周期与要创建的对象的生命周期不重叠,则必须推迟构造函数的执行,直到需要创建对象。这就是为什么你需要有一个工厂。此时您可以将工厂方法传递给您的映射,从而传递生成对象所需的信息,但允许在需要时进行创建,而不是在执行组合根时。
你不需要工厂类来做这个工厂方法很好,而且工厂方法可以内联,所以代码开销并不比我们在组合路由中创建对象多多少。
如果我们有一个包含 2 个服务的项目,其中第一个服务依赖于第一个服务,并且我们只希望第二个服务的生命周期在我们创建第一个服务时开始,我们可能会有如下内容。(我正在使用 ninject 给出一个代码示例,但我希望其他 IOC 容器在这方面也能类似地工作。)
`
公共类Service1:IService
{
私有 Func<IService>serviceFactoryMethod _Service2Factory;
公共服务1(Func<IService>service2FactoryMethod)
{
_Service2Factory=service2FactoryMethod;
}
公共无效 DoSomethingUsingService2()
{
var service2=_Service2Factory();
service2.DoSomething();
}
}
公共类主类
{
公共无效CompositionRoot()
{
var kernel= new StandardKernel();
kernel.Bind.ToMethod(m=>
{
return new Service1(m.Kernel.Get<IService2>());
}
}
}
`
这个例子没有说明你将如何管理应用程序的生命周期、玩家和游戏的生命周期,但希望它能提供足够的线索来说明如何消除与依赖注入相关的生命周期问题。
旁注:使用 Ninject,您将能够更改 Service2 的范围,以便管理其生命周期,使其超出 Service1 的生命周期。例如,如果您知道游戏的每个实例都将在其自己的线程上发生(好吧,这可能不太可能),您可以为游戏使用 InThreadScope。