代码之家  ›  专栏  ›  技术社区  ›  Bullines

反思的工作?

  •  1
  • Bullines  · 技术社区  · 17 年前

    我有一个类用作缓存:

    public sealed class MyCache<T> : IDisposable
    {
        private ReaderWriterLockSlim theLock = new ReaderWriterLockSlim();
        private Dictionary<int, T> theCache = new Dictionary<int, T>();
    
        public void Add(int key, T value)
        {
            // ... logic/code to add to the dictionary
        }
    
        public void Clear()
        {
            theLock.EnterWriteLock();
            try
            {
                theCache.Clear();
            }
            finally
            {
                theLock.ExitWriteLock();
            }
        }
    }
    

    这个缓存被多次使用,因此在任何给定的时间经常有多个这样的实例。

    public static class SpecialPageCache
    {
        public static MyCache<string> SpecialPage = new MyCache<string>();
    }
    

    例2:

    public static class DdListCache
    {
        public static MyCache<List<int, string>> DdlList = new MyCache<List<int, string>>();
    }
    

    等等。

    private void ClearThemAll()
    {
        SpecialPageCache.SpecialPage.Clear();
        DdListCache.DdlList.Clear();
        // repeat for all other caches that may exist ...
    }
    

    我如何使用反射(或其他东西?)要调用每个缓存的Clear()方法而不必像我在上面的ClearThemAll()方法中那样为每个缓存显式地调用它?

    7 回复  |  直到 17 年前
        1
  •  3
  •   Jon Skeet    17 年前

    依克。您必须检查程序集中您感兴趣的所有类型,并检查所有静态字段。这变得更加有趣,因为它是一个泛型类型。如果你有一个非普通的基类,你的生活会更简单:

    public abstract class MyCache : IDisposable
    {
        public abstract void Clear();
    }
    
    public sealed class MyCache<T> : MyCache
    {
        // ...
    }
    

    MyCache ,获取其值并调用 Clear 在它上面,而不是在泛型类型上进行反射。

    不过,这通常是一个棘手的问题-你确定要清除所有这样的缓存,而不是真正“理解”你清除的缓存?

        2
  •  3
  •   BFree    17 年前
    public interface ICache : IDisposable
    {
        void Clear();
    }
    
    public interface ICache<T> : ICache
    {
    }
    
    public abstract class CacheBase<T> : ICache<T>
    {
    
    }
    
    public sealed class SpecialPageCache : CacheBase<string>
    {
        internal SpecialPageCache()
        {
        }
    
    }
    
    public static class CacheFactory
    {
        private static List<ICache> cacheList = new List<ICache>();
    
        public static TCache Create<TCache>()
            where TCache : ICache, new()
        {
            var result = new TCache();
            cacheList.Add(result);
            return result;
        }
    
        public static void ClearAll()
        {
            cacheList.ForEach((c) => c.Clear());
        }
    }
    
        3
  •  1
  •   J. Steen    17 年前

    可以将对所有实例缓存的引用存储在列表中。然后迭代相同的列表,并对每个MyCache调用Clear。=)

        4
  •  1
  •   Mikko Rantanen    17 年前

    倒影听起来很恶心。如果不知道更多关于对象生命周期的信息,下面的方法是否有效?

    public abstract class MyCacheBase : IDisposable {
        public static List<MyCache> caches = new List<MyCache>();
    
        public MyCacheBase() {
            caches.Add(this); // Add all constructed caches to the list
        }
    
        public static void ClearAllCaches() {
            foreach (MyCache cache in cache) // clear all constructed
                cache.Clear();               // caches in the list.
        }
    
        public void Finalize() {
            Dispose();
        }
    
        public void Dispose() {
            caches.Remove(this);  // Remove disposed classes from the list
        }
    
        public abstract void Clear();
    }
    
    public sealed class MyCache<T> : MyCacheBase
    {
        // Rest of the implementation
    }
    

    如果你想拥有类似于用户特定的缓存,你可以添加一个用户特定的缓存工厂来跟踪通过它创建的缓存,它的ClearAll()方法只会清除那些缓存。

        5
  •  1
  •   Mark Broadhurst    17 年前

    为什么你需要明确的澄清他们是否在使用需要释放的资源?

    我想知道您是否不能使用System.WeakReference以便在何时收集garbarge缓存?

    http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

        6
  •  0
  •   Jacob Adams    17 年前

    这听起来很熟悉控制容器的反转是如何工作的。为什么不做点像

    Dictionary<Type, Dictionary<int, object>>

    然后,所有的函数都采用T类型,然后使用该类型查找相应的字典。一个静态MyCache可以处理您的所有类型,并且可以用一个调用释放它。

        7
  •  0
  •   Colin Burnett    17 年前

    如果你真的想思考,那么你应该这样做:

    List<object> caches;
    foreach (object obj in caches)
    {
        Type t = obj.GetType();
        MethodInfo m = t.GetMethod("Clear");
    
        // Object does not have a public instance method named "Clear"
        if (m == null) { continue; }
    
        m.Invoke(obj, new object[0]);
    }