原型对象和"每个图形"DI 生命周期



我有一个Credentials类,它应该通过依赖注入作为实例提供给所有需要它的构造函数。目前,我已经通过将该类的一个实例注册到我的DI容器中来解决这个问题,该实例具有单例生命周期。这确保了在每次DI调用时,所有对象都接收到相同的凭据。这是可行的,但有点尴尬,因为Credentials单例的属性在每次显式DI调用之间都会发生变化。这意味着每个接收方构造函数必须立即";抓取并保存";在Credentials实例的属性更改之前对其进行凭据验证。

如果我可以让DI容器为每个图或每次调用创建一个新的Credentials实例,这会更好(是的,GOF"prototype"模式(。我使用的是Simple Injector,所以我的第一个解决方案是这样的:

public static Credentials creds; //Implements ICloneable
//....
var prototypeTransientLifestyle = Lifestyle.CreateCustom(
name: "Prototype Transient",
// instanceCreator is of type Func<object>
lifestyleApplierFactory: instanceCreator =>
{
return () => creds.Clone();
});

我认为这是可行的,但即便如此,它也有两个弱点。首先,它只能应用于我的Credentials类。我希望它可以通用地重复使用。其次,它在一个显式的DI调用中可能会创建许多克隆。我希望它有";每个图";生命周期,以便它只创建一次克隆,并在DI调用的剩余部分中重新使用它。

有什么想法可以继续吗?

顺便说一句,我知道";每个图";生命周期存在与惰性评估相关的问题。我没有任何懒惰的评价,所以这不是一个问题。

更新

我想我的问题有部分解决办法。为了以通用的方式实现原型克隆,我可以这样做:

container.Register<Credentials>(() => (Credentials)creds.Clone());

现在我仍然想拥有";每个图";行为进一步的阅读表明我需要使用SimpleInjectorScope。显然,这需要我有一个调用DI容器的中心位置,这样我就可以显式地创建作用域。我的代码确实非常适合这一点,但我仍然想知道是否有另一种方法可以实现";每个图";这不需要显式地创建范围。

正如文档中所指出的,Simple Injector没有";每个图";生活方式相反,Scoped生活方式提供的行为通常足够接近。

显然,这需要我有一个调用DI容器的中心位置,这样我就可以显式地创建作用域。

这是正确的。这个中心位置被称为CompositionRoot,每个应用程序都会有它

我仍然想知道是否还有另一种方法可以实现";每个图";这不需要显式地创建范围。

Simple Injector GitHub存储库包含一个演示Per Graph生活方式的代码示例,但我的建议是坚持使用内置结构,即ScopedLifestyle

最新更新