我有一个缓存类,使用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<>
的依赖是不可能实现的。该关系类型旨在支持multiple implementations of a service,而不是用于解析所有实例。
我不知道有什么方法可以做你想做的事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。