为跨多个程序集的特定类型的实例实施中央 'manager' class

Implementing a central 'manager' class for instances of a specific type across multiple assemblies

在我们的软件中,我们有时会使用特定的 class 来缓存键和值的组合,以防止从数据库中重复检索相同的值。因为缓存的实现越来越多,所以我想集中管理所有的缓存实现,把不同缓存的实现归纳起来classes.

因此,我创建了一个通用的 'Cache' class,它是静态 CacheManager class 的私有嵌套 class。由于私有嵌套缓存 class,此 class 无法由 CacheManager 本身以外的任何其他 class 启动。

我想使用缓存管理器的原因是因为我希望能够刷新所有现金并获取所有缓存的统计信息,而不会丢失我不知道的缓存实现(由同事创建)。

ICache 接口用于向 CacheManager 外部的代码公开缓存 class。

简化的实现:

界面

// Interface for all available caches
    public interface ICache<TKey, TValue>
    {
        bool            StatisticsEnabled   { get; set; }
        KeyStatistics[] Statistics          { get; }

        // Set cache item (including update)
        void Set(TKey key, TValue item);

        // Get an item from the cache (return value indicates found / not found in cache)
        bool Get(TKey key, out TValue value);
    }

用于统计的数据对象

    // Statistics per key in the cache (or requested from the cache)
    public class KeyStatistics
    {
        public string Name { get; set; }
        public int RequestCount { get; set; }
        public int HitCount { get; set; }
    }

    // Contains statistics per cache
    public class CacheStatistics
    {
        public string           Name        { get; set; }
        public KeyStatistics[]  Statistics  { get; set; } 
    }

包括通用缓存实现的静态缓存管理器

    public static class CacheManager 
    {
        private static Lazy<Cache<string, string>> _settingsCache = new Lazy<Cache<string, string>>();
        private static Lazy<Cache<DateTime, short>> _mechanicCountCache = new Lazy<Cache<DateTime, short>>();

        // actual supported caches
        public static ICache<string, string> SettingsCache { get { return _settingsCache.Value; } }
        public static ICache<DateTime, short> MechanicCountCache { get { return _mechanicCountCache.Value; } }

        public static IEnumerable<CacheStatistics> Statistics
        {
            get 
            {
                yield return new CacheStatistics
                {
                    Name        = "Settings cache",
                    Statistics  = _settingsCache.Value.Statistics
                };
                yield return new CacheStatistics
                {
                    Name        = "Mechanics count cache",
                    Statistics = _mechanicCountCache.Value.Statistics
                };
            }
        }

        // Private class, so it cannot be initiated by anything else than the cache manager
        private class Cache<TKey, TValue> : ICache<TKey, TValue>
        {
            private ConcurrentDictionary<TKey, KeyStatistics> _statistics = new ConcurrentDictionary<TKey, KeyStatistics>();
            private ConcurrentDictionary<TKey, TValue> _cachedValues = new ConcurrentDictionary<TKey, TValue>();

            // Constructor
            public Cache() 
            {
                // Do some constructing things  
            }

            #region ICache
            public bool StatisticsEnabled { get; set; }

            public KeyStatistics[] Statistics
            {
                get { return _statistics.Values.ToArray(); }    
            }

            public void Set(TKey key, TValue item) 
            {
                // Todo: add to cache or update existing value

            }

            public bool Get(TKey key, out TValue item) 
            {
                // Todo: fetch from dictionary
                // Todo: update statistics

                item = default(TValue);
                return false;
            }

            #endregion ICache
        }

这将按要求工作。但是,有些事情我还没有弄清楚。我们使用多个程序集(核心程序集和 'specialized' 程序集)。专用程序集引用了核心程序集,但反之则不然。

我希望 CacheManager(核心程序集的一部分)能够管理来自专门程序集的 TValue 类型的缓存。我希望缓存也只能从专门的程序集中可见。我知道我不能使用部分 classes,我也不认为扩展会帮助我。

有没有办法实现我想要的?

您只能在缓存管理器本身中存储序列化的对象值。引用程序集是否具有适当的专用程序集引用取决于引用程序集。

Json.NET 过去对通用对象 serialization/deserialization.

很有效

我最终在核心程序集中有了一个缓存管理器。此缓存管理器不知道引用程序集中的专用缓存类型。相反,它有一个使用泛型类型调用的 'GetCache()' 方法。泛型类型必须是 'ICache'.

的实现

在 'GetCache' 的实现中,缓存管理器使用通用 'Singleton' class 可以创建类型的单例实例(在本例中是实现 ICache 的类型) .

翻译: * GetStatistieken() > GetStatistics() * Wissen() > 清除所有缓存内容

在引用程序集中,可以像这样获取缓存实例:

var cache = CacheManager.GetCache<DagCapaciteitCache>();

为了便于创建新缓存,缓存实例可以子class两个缓存基class之一,但这不是必需的。唯一的要求是缓存实现 IQuery 接口(在核心程序集中定义)。

OP 有点晚了。对于其他人来说,实施工厂模式可能是可行的方法。然后使用反射来获取通过工厂实现的所有类型,并迭代以重置 all/specific 缓存。

例如 https://www.dofactory.com/net/factory-method-design-pattern

希望对您有所帮助。