首页 > 解决方案 > 带有事件处理程序的 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 的依赖项。

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

标签: c#design-patternsdependency-injectionautofac

解决方案


通过依赖IEnumerable<>. 该关系类型旨在支持服务的多个实现,而不是用于解析所有实例。

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

AddNotifier()将每个添加到一个集合中,然后从ExecuteCacheCleared().

这将非常复杂,因为在多线程环境中您必须非常小心地处理此代码——您肯定在其中,因为您使用的是InstancePerRequest(). 此外,您将不得不想办法在请求完成时删除所有这些实例(使用WeakReferences? Make ICacheClearedimplement的集合并在处置时IDisposable调用 a ?)。ICacheService.Remove()可能还有许多我没有考虑过的其他问题。

这非常复杂,您可能需要花点时间重新考虑设计本身,然后再进入兔子洞。

祝你好运!


推荐阅读