2
\$\begingroup\$

I am trying to implement a singleton CacheDependencyManager, by combining this CacheDependencyManager from Steve Greatrex with a singleton pattern from Jon Skeet (example 6).

I'd really appreciate any feedback on it's correctness and / or suggestions for improvement.


ExplicitCacheDependency

public class ExplicitCacheDependency : CacheDependency
{
    private string _uniqueId;

    public ExplicitCacheDependency(string uniqueId)
        : base(new string[0]) //no file system dependencies
    {
        _uniqueId = uniqueId;
    }

    public override string GetUniqueID()
    {
        return _uniqueId;
    }


    // CacheDependency has a protected NotifyDependencyChanged method that will notify the caching framework that the cached item is no longer valid. 
    // In most implementations this would be invoked in some callback, but for our purposes we can just add a new Invalidate method and invoke it directly
    public void Invalidate()
    {
        base.NotifyDependencyChanged(this, EventArgs.Empty);
    }
}

CacheDependencyManager

public sealed class CacheDependencyManager
{
    private static readonly Lazy<CacheDependencyManager> lazy =
        new Lazy<CacheDependencyManager>(() => new CacheDependencyManager());

    public static CacheDependencyManager Instance { get { return lazy.Value; } }

    private CacheDependencyManager()
    {
    }


    private Dictionary<string, ExplicitCacheDependency> _dependencies
        = new Dictionary<string, ExplicitCacheDependency>();

    public CacheDependency GetCacheDependency(string key)
    {
        if (!_dependencies.ContainsKey(key))
            _dependencies.Add(key, new ExplicitCacheDependency(key));

        return _dependencies[key];
    }

    public void InvalidateDependency(string key)
    {
        if (_dependencies.ContainsKey(key))
        {
            var dependency = _dependencies[key];
            dependency.Invalidate();
            dependency.Dispose();
            _dependencies.Remove(key);
        }
    }
}
\$\endgroup\$
3
\$\begingroup\$

As CacheDependencyManager is a singleton it should be thread safe.

ConcurrentDictionary is a nice fit for this.

Using ConcurrentDictionarythe code would look like this:

private ConcurrentDictionary<string, ExplicitCacheDependency> _dependencies = new ConcurrentDictionary<string, ExplicitCacheDependency>();

public CacheDependency GetCacheDependency(string key)
{
    return _dependencies.GetOrAdd(key, k => new ExplicitCacheDependency(k));
}

public void InvalidateDependency(string key)
{
    ExplicitCacheDependency dependency;
    if (_dependencies.TryRemove(key, out dependency))
    {
        dependency.Invalidate();
        dependency.Dispose();
    }
}
\$\endgroup\$
  • \$\begingroup\$ ConcurrentDictionary looks interesting, I've never come across that before. Doesn't using System.Lazy<T> make it thread safe? Or have I got the wrong end of the stick? \$\endgroup\$ – Martin Hansen Lennox Mar 4 '16 at 23:03
  • \$\begingroup\$ I can see how Lazy<T> makes initialization thread safe but nothing more. \$\endgroup\$ – Johan Larsson Mar 4 '16 at 23:20
  • \$\begingroup\$ Ah ok, I can see I need to look into this more. In the meantime I'll implement your suggestion... thanks! \$\endgroup\$ – Martin Hansen Lennox Mar 4 '16 at 23:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.