具有事件处理程序的 Autofac 单个实例



我有一个缓存类,它被注册为Autofac的单个实例。每当我清除缓存时,我都会调用该方法ExecuteCacheCleared();

缓存类如下所示

public IEnumerable<ICacheCleared> _cacheCleared { get; private set; }
public CacheService(IEnumerable<ICacheCleared> cacheCleared) : ICacheService
{
_cacheCleared = cacheCleared;
}
private void ExecuteCacheCleared()
{
if (_cacheCleared != null)
{
foreach (var cacheCleared in _cacheCleared)
{
cacheCleared.EntityCacheChanged();
}
}
}

然后,我有几个具体的ICacheCleared实现,当调用ExecuteCacheCleared时会调用它们。

所以目前我在 autofac 中注册位,如下所示:

builder.RegisterType<CacheService>().As<ICacheService>().SingleInstance();
builder.RegisterType<CacheCleared>().As<ICacheCleared>().InstancePerRequest();

综上所述,我得到了一个错误(我得到的(,因为 SingleInstance 无法与 InstancePerRequest 一起使用,但在我的 CacheCleared 具体类中,我还注入了需要成为 InstancePerRequest 的其他依赖项。

希望你能看到我想要实现的目标(基本上是试图通知订阅类的更改(,但我坚持如何实现这一目标。

通过依赖IEnumerable<>,您将无法尝试执行的操作。该关系类型旨在支持服务的多个实现,而不是用于解析所有实例。

我不知道有什么方法可以做你想做的事情 OOTB。这是一个相当深奥和困难的场景。我能想到的最好的方法是反转控件:要求你的ICachedCleared实现依赖于ICacheService。反过来,给ICacheService一个像AddNotifier(ICacheCleared)这样的方法,可以从构造函数调用(如果它很便宜 - 我强烈建议让它便宜(或在第一次使用时调用(如果它很贵 - 例如,返回一个Task(。

AddNotifier()会将每个添加到集合中,然后从ExecuteCacheCleared()调用该集合。

这将是非常复杂的,因为您必须在多线程环境中非常小心此代码 - 您肯定处于多线程环境中,因为您正在使用InstancePerRequest()。此外,您还必须找到一种方法在请求完成后删除所有这些实例(使用WeakReferences的集合?使ICacheCleared实现IDisposable并在释放时调用ICacheService.Remove()?可能还有许多其他我没有考虑过的问题。

这的复杂性足够高,以至于您可能需要花点时间重新考虑设计本身,然后再进入兔子洞。

祝你好运!

目前还不完全清楚你的设计意图是什么。我正在使用 autofac,并且具有每个请求实例化的缓存和其他单个实例化的缓存。 通常,请求应该是短暂的,每个请求缓存的任何内容都应该是请求时的快照。

我们为每个请求缓存的数据通常是为了避免在一个请求中重新加载或重新计算数据。您要求清除每个请求实例化的缓存是可疑的,更可疑的是您想清除所有当前请求中的这些缓存,我不明白您如何或为什么需要这样的功能。

无论如何,我认为答案可能非常简单。ICacheService也需要是InstancePerRequest或者 ICacheCleared需要是单实例的。

或者,您应该分解缓存的设计,以便将每个请求实例化的缓存与单个实例化的缓存分开。 即有一个ICacheService,它有一个ICacheCleared的集合和一个IRequestCacheService,它有一个IRequestCacheCleared对象的集合。

您可以将单个实例化对象注入到每个请求实例化的对象中,反之则不然。 因此,如果你喜欢IRequestCacheService,也可以注入ICacheService,并在IRequestCacheService上调用ExecuteCacheCleared时在ICacheService上调用ExecuteCacheCleared

最新更新