2

我有下面的代码,现在我想添加一个UpdateSetting方法。

我能看到的最好的方法是通过TryUpdateon the ,ConcurrentDictionary但这意味着知道以前的值,因此需要调用GetSetting似乎有点恶心的调用。你怎么认为?有没有更好的办法?

注意:如果该值不在缓存中,它应该什么都不做。在成功更新缓存时,它应该调用settingRepository.Update

谢谢

public class MySettings : IMySettings
    {
        private readonly ISettingRepository settingRepository;
        private readonly ConcurrentDictionary<string, object> cachedValues = new ConcurrentDictionary<string, object>();


        public MySettings(ISettingRepository settingRepository)
        {
            this.settingRepository = settingRepository;
        }

        public string GetSetting(string key)
        {
            return this.GetSetting<string>(key);
        }

        public T GetSetting<T>(string key)
        {
            object value;
            if (!this.cachedValues.TryGetValue(key, out value))
            {
                value = this.GetValueFromRepository(key, typeof(T));
                this.cachedValues.TryAdd(key, value);
            }

            return (T)value;
        }

        private object GetValueFromRepository(string key, Type type)
        {
            var stringValue = this.settingRepository.GetSetting(key);
            if (stringValue == null)
            {
                throw new MissingSettingException(string.Format("A setting with the key '{0}' does not exist.", key));
            }

            if (type == typeof(string))
            {
                return stringValue;
            }

            return ConvertValue(stringValue, type);
        }

        private static object ConvertValue(string stringValue, Type type)
        {
            return TypeDescriptor.GetConverter(type).ConvertFromString(stringValue);
        }

    }
4

2 回答 2

0

一种方法是简单地设置值,并捕获如果键不在集合中它将抛出的异常。

    public bool UpdateSetting<T>(string key, T value)
    {
        try {
            this.cachedValues[key] = value;
        } catch (KeyNotFoundException ex) {
            return false;
        }
        return true;
    }

这是否是您想要处理不存在的密钥的方式取决于您。但是如果您决定要添加密钥,那么您应该使用AddOrUpdate方法而不是上面的简单赋值。在这种情况下,您不需要捕获该异常。

为了解决您的支持存储库的更大问题,我认为您需要一些类似的东西。

    public bool UpdateSetting<T>(string key, T value)
    {
        lock {
            try {
                this.cachedValues[key] = value;
                this.settingRepository.Update(... //you'll have to write this
            } catch (KeyNotFoundException ex) { 
                return false;
            }
            return true;
        }
    }

我认为您不能避免使用锁来确保对缓存的更改与存储库匹配。出于同样的原因,我认为您现有的一些代码也可能需要锁定。使用 ConcurrentDictionary 仅在对字典的操作中保护您。但在更大的范围内,还有更多的事情需要同步。

于 2015-01-23T18:43:32.560 回答
0

可能值得获取现有值以避免更新存储库。如果比尝试更昂贵,则例外

public bool UpdateSetting<T>(string key, T value)
{
    lock 
    {
        T oldValue;            
        if (this.cachedValues.TryGetValue(key, out oldValue)
        {
            if (oldValue != value)
            {
                this.cachedValues[key] = value;
                settingRepository.Update(key, value);
            }
            return true;
        } 
        else 
        { 
           return false;
        }            
    }
}
于 2015-01-23T19:12:06.823 回答