原型对象和 "Per Graph" DI 生命周期

Prototype objects and "Per Graph" DI Lifecycle

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

如果我能让 DI 容器创建一个新的 Credentials 实例,每个图形或每个调用,它会基于原型对象(是的,GOF“原型“ 图案)。我正在使用 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();
    });

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

关于如何进行的任何想法?

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

更新

我想我已经部​​分解决了我的问题。要以通用方式实现原型克隆,我可以这样做:

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

现在我仍然想要“按图”行为。进一步阅读表明我需要使用简单注入器 Scope。显然,这需要我有一个调用 DI 容器的中心位置,以便我可以显式创建范围。我的代码确实非常适合,但我仍然想知道是否有另一种方法可以实现“每个图”,而无需显式创建范围。

如文档中的 noted 所示,Simple Injector 没有“按图”生活方式的概念。相反,Scoped 生活方式提供的行为通常足够接近。

Apparently this requires that I have a central location where my DI container is invoked, so that I can explicitly create the scope.

没错。这个中心位置称为 Composition Root,每个应用程序都会有它。

I'm still wondering if there is another way to achieve "per graph" which does not require explicitly creating a scope.

Simple Injector GitHub 存储库包含 a code example that demonstrates the Per Graph lifestyle,但我的建议是坚持使用内置构造,​​即 ScopedLifestyle.