1

主な機能は Web サービスからオブジェクトを取得し、Web サービス キャッシュ ヘッダーの応答に応じてキャッシュするシングルトン プロバイダーです。このオブジェクトは非常に頻繁にアクセスされます。私の質問は、Web サービスのデータがいつ変更されるかということです。それ以降のシングルトンへの呼び出しは自動的に反映されますか?

public class ConfigurationProvider
{
    #region Private Member Variables
    private static readonly Lazy<ConfigurationProvider> _instance = new Lazy<ConfigurationProvider>(() => new ConfigurationProvider());
    private static readonly HttpCache _cache = new HttpCache(); 
    #endregion

    #region Constructors
    private ConfigurationProvider()
    {

    } 
    #endregion

    #region Public Properties
    public static ConfigurationProvider Instance
    {
        get { return _instance.Value; }
    }

    public ShowJsonResponse Configuration
    {
        get
        {
            // Try and get the configurations from webservice and add to cache
            var cacheExpiry = 0;
            return _cache.GetAndSet(WebApiConstant.ProxyCacheKeys.ShowJsonKey, ref cacheExpiry, () => GetConfiguration(ref cacheExpiry));
        }
    } 
    #endregion

    #region Private Methods
    private ShowJsonResponse GetConfiguration(ref int cacheExpiry)
    {
        var httpClient = new HttpClient();

        try
        {
            var response = httpClient.GetAsync(WebApiConstant.Configuration.WebserviceUrl).Result;

            if (response.IsSuccessStatusCode)
            {
                var showResponse = response.Content.ReadAsAsync<ShowJsonResponse>().Result;

                if (response.Headers.CacheControl.Public && response.Headers.CacheControl.MaxAge.HasValue)
                {
                    cacheExpiry = response.Headers.CacheControl.MaxAge.Value.Seconds;
                }

                // TODO: Remove when finished testing
                // Default to 60 seconds for testing
                cacheExpiry = 20;
                return showResponse;
            }

        }
        catch (HttpRequestException ex)
        {

        }

        cacheExpiry = 0;
        return null;
    } 
    #endregion
}

HttpCache クラスは、HttpRuntime Cache の単なるラッパーです。GetAndSet メソッドは、キャッシュ オブジェクトの取得を試み、見つからない場合はそれを設定します。

public override T GetAndSet<T>(string key, ref int duration, Func<T> method)
    {
        var data = _cache == null ? default(T) : (T) _cache[key];

        if (data == null)
        {
            data = method();

            if (duration > 0 && data != null)
            {
                lock (sync)
                {
                    _cache.Insert(key, data, null, DateTime.Now.AddSeconds(duration), Cache.NoSlidingExpiration);
                }
            }
        }

        return data;
    }

使用例:

ConfigurationProvider.Instance.Configuration.Blah

このシナリオでシングルトン パターンを使用するメリットはありますか、それともクラスを定期的にインスタンス化しても問題ありませんか?

4

1 に答える 1

0

あなたのケースにはシングルトン パターンの方が適していると思います。オブジェクト インスタンスも必要ありません。HttpCache ラッパー内で並行処理を行っていますか? 複数のスレッドが同時にキャッシュ オブジェクトにアクセスする場合、または WS リクエストが返される前に複数の WS リクエストを作成する可能性を回避するために重要です。

ダブル ロック/チェック パターンを使用することをお勧めします。

public override T GetAndSet<T>(string key, ref int duration, Func<T> method) {
    var data = _cache == null ? default(T) : (T) _cache[key];

    if (data == null) { //check
        lock (sync) { //lock

            //this avoids that a waiting thread reloads the configuration again
            data = _cache == null ? default(T) : (T) _cache[key];
            if (data == null) { //check again
                data = method();

                if (duration > 0 && data != null) {                 
                    _cache.Insert(key, data, null, DateTime.Now.AddSeconds(duration), Cache.NoSlidingExpiration);
                }
            }
        }
    }

    return data;
}
于 2013-08-12T03:03:43.640 に答える