如何在 DryIoC 中删除(设置为 null)已注册的单例类型?



我需要完全删除已由 DryIoC 容器解析的实例(但不能注销类型(。我不知道这是否可能?

如果我不使用任何 IoC 容器,只是自己声明单例,我当然可以随时轻松地将其重置为 null。

例如:

var instance = DryIocContainer.Resolve<SomeType>();//a singleton
//All next times calling Resolve<> will return just that singleton instance.
//But if that is cleared, the next time calling Resolve<> should create 
//a completely new instance (like as the first time it was called).

此处的情况是在用户注销我的应用程序后,我想清除所有已解析的单例,以便如果用户使用另一个帐户(甚至使用相同的帐户(重新登录,数据将正确刷新。目前无法清除这些单例,我必须自己手动重置所有属性 - 我认为这应该是最后的手段。

我不知道

这是否可能?

不,这实际上是不可能的。尽管Dadhi指出了WithoutSingletonsAndCache方法,但这有效地构建了一个具有一组新实例的新容器。虽然这允许您替换特定的单例,但这也意味着所有其他单例注册将被清除,并且您将失去只有一个特定类型实例的承诺。换句话说,为了能够做到这一点,容器已经打破了它对单例的承诺。这实际上导致了撕裂的生活方式。您将仔细分析这是否是一个问题。

如果我不使用任何 IoC 容器,只是自己声明单例,我当然可以随时轻松地将其重置为 null。

这不是真的。即使没有容器,也不能简单地替换单例。一个简单的例子是,当要替换的这个单例是另一个单例的依赖项时。除非您替换该单一实例(及其链上的所有单一实例使用者(,否则此原始实例将在其使用者中捕获,并且即使您尝试替换原始实例,使用者也会继续引用原始实例。这是强制依赖问题的一种形式。

解决此问题并仅针对此实例在本地解决该问题的唯一真正方法是为该单例的抽象创建一个代理。此代理可以包装该依赖项,您可以允许稍后更改它。这允许您随时替换依赖项。

如何实现这一点在很大程度上取决于您的特定需求,但这里有一个例子:

public interface ISomeType
{
void SomeMethod();
}
public class SomeTypeImpl : ISomeType { ... }
public class SomeTypeProxy : ISomeType
{
public ISomeType Dependency { get; set; }
public SomeTypeProxy(ISomeType dependency) {
this.Dependency = dependency;
}
public void SomeMethod() => this.Dependency.SomeMethod();
}

如果没有 DI 容器,可以按如下方式使用它:

var proxy = new SomeTypeProxy(new SomeTypeImpl());
// later on
proxy.Dependency = new OtherTypeImpl();

另一种选择是让代理包装Func<T>委托,这允许您将此逻辑移动到委托:

ISomeType dependency = new SomeTypeImpl();
var proxy = new SomeTypeProxy(() => dependency);
// later on
dependency = new OtherTypeImpl();

这里的场景是在用户注销我的应用程序后,我想清除所有已解决的单例,以便如果用户使用另一个帐户重新登录

在您的特定情况下,您实际上是在描述清除整个应用程序。你的方案听起来类似于重新排列应用程序。这可能是WithoutSingletonsAndCache擅长的事情,因为您希望重置所有单例。

但是,只需创建一个包含其所有注册的新容器即可实现相同的目标。您的应用程序已经具有某种CreateContainer类,并且应该再次调用该CreateContainer方法。

当然,此方法仅在处理应用程序时有效,而不是让 Web 应用程序同时为多个用户运行请求。

你可以做:

container = container.WithoutSingletonsAndCache();

这是文档。

最新更新