如何实现一个线程安全的单例字典类进行缓存?

时间:2022-07-14 19:50:45

I am trying to implement a thread safe dictionary singleton class for caching purpose.

我试图实现一个线程安全字典单例类用于缓存目的。

namespace SingletomDict
{
public sealed class MySingleton:IDisposable
{
    private static readonly Lazy<MySingleton> coll = new Lazy<MySingleton>(() => new MySingleton());

    private static Dictionary<string, object> mycoll;

    public static MySingleton Instance 
    {
        get
        {
            return coll.Value;
        }
    }

    private MySingleton()
    {
        mycoll = new Dictionary<string, object>();
    }

    private void SetProperty<T>(string name, T value)
    {
        mycoll.Add(name, value);
    }

    private object GetProperty(string name)
    {
        object value = mycoll[name];
        return value;
    }

    public dynamic this[string index]
    {
        get { return GetProperty(index); }
        set { SetProperty(index, value); }
    }
    public void ReSet()
    {
        mycoll = new Dictionary<string, object>();
    }
}

In the main method, I will be invoking the object as

在main方法中,我将调用该对象作为

  MySingleton.Instance["LS"] = "AAA";

  MySingleton.Instance["AB"] = "BBB";

  MySingleton.Instance.ReSet();

I did some research to find the correct implementation. But I couldn't find the appropriate example. Thanks

我做了一些研究以找到正确的实现。但我找不到合适的例子。谢谢

1 个解决方案

#1


0  

First declare an interface that describes how you want to use this. Perhaps ICache with a get and set method. (I'd steer clear of dynamic.)

首先声明一个描述如何使用它的接口。也许ICache有一个get和set方法。 (我避开动态。)

public interface ICache
{
    T Get<T>(string key);
    void Set(string key, object value);
}

Then write an implementation. Your implementation doesn't need to specify what the internals are.

然后编写一个实现。您的实现不需要指定内部是什么。

public class Cache : ICache
{
    private readonly ConcurrentDictionary<string, object> _cache 
        = new ConcurrentDictionary<string, object>();
    public T Get<T>(string key)
    {
        object cached;
        if(_cache.TryGetValue(key, out cached) && cached is T)
        {
            return(T) cached;
        }
        return default(T);
    }

    public void Set(string key, object value)
    {
        _cache.AddOrUpdate(key, value, (s, o) => value);
    }
}

If you want to make this a singleton, you can make the constructor private and create a static singleton instance. I would lean toward not doing that. It's better for other classes to depend on the ICache interface than on the implementation, and an interface doesn't have static methods.

如果要使其成为单例,可以将构造函数设为私有并创建静态单例实例。我倾向于不这样做。对于其他类来说,依赖于ICache接口比在实现上更好,并且接口没有静态方法。

Depending on the interface means that you can substitute it with different implementations, like one that depends on MemoryCache.

根据接口的不同,您可以将其替换为不同的实现,例如依赖于MemoryCache的实现。

public class InMemoryCache : ICache
{
    private readonly MemoryCache _cache = MemoryCache.Default;

    public T Get<T>(string key)
    {
        var cached = _cache[key];
        return cached is T ? (T) cached : default(T);
    }

    public void Set(string key, object value)
    {
        _cache[key] = value;
    }
}

If you use a dependency injection (IoC) container you can tell it which implementation of ICache to use for a class that needs an instance of it, and you can specify that the same instance should be provided each time. That way you get to use a single instance of your class as if it was a singleton without having to code it as a singleton.

如果使用依赖注入(IoC)容器,则可以告诉它要将ICache的哪个实现用于需要其实例的类,并且可以指定每次都应提供相同的实例。这样你就可以使用你的类的单个实例,就好像它是一个单例,而不必将它编码为单例。

#1


0  

First declare an interface that describes how you want to use this. Perhaps ICache with a get and set method. (I'd steer clear of dynamic.)

首先声明一个描述如何使用它的接口。也许ICache有一个get和set方法。 (我避开动态。)

public interface ICache
{
    T Get<T>(string key);
    void Set(string key, object value);
}

Then write an implementation. Your implementation doesn't need to specify what the internals are.

然后编写一个实现。您的实现不需要指定内部是什么。

public class Cache : ICache
{
    private readonly ConcurrentDictionary<string, object> _cache 
        = new ConcurrentDictionary<string, object>();
    public T Get<T>(string key)
    {
        object cached;
        if(_cache.TryGetValue(key, out cached) && cached is T)
        {
            return(T) cached;
        }
        return default(T);
    }

    public void Set(string key, object value)
    {
        _cache.AddOrUpdate(key, value, (s, o) => value);
    }
}

If you want to make this a singleton, you can make the constructor private and create a static singleton instance. I would lean toward not doing that. It's better for other classes to depend on the ICache interface than on the implementation, and an interface doesn't have static methods.

如果要使其成为单例,可以将构造函数设为私有并创建静态单例实例。我倾向于不这样做。对于其他类来说,依赖于ICache接口比在实现上更好,并且接口没有静态方法。

Depending on the interface means that you can substitute it with different implementations, like one that depends on MemoryCache.

根据接口的不同,您可以将其替换为不同的实现,例如依赖于MemoryCache的实现。

public class InMemoryCache : ICache
{
    private readonly MemoryCache _cache = MemoryCache.Default;

    public T Get<T>(string key)
    {
        var cached = _cache[key];
        return cached is T ? (T) cached : default(T);
    }

    public void Set(string key, object value)
    {
        _cache[key] = value;
    }
}

If you use a dependency injection (IoC) container you can tell it which implementation of ICache to use for a class that needs an instance of it, and you can specify that the same instance should be provided each time. That way you get to use a single instance of your class as if it was a singleton without having to code it as a singleton.

如果使用依赖注入(IoC)容器,则可以告诉它要将ICache的哪个实现用于需要其实例的类,并且可以指定每次都应提供相同的实例。这样你就可以使用你的类的单个实例,就好像它是一个单例,而不必将它编码为单例。