Является ли этот модифицированный шаблон C # singleton хорошей практикой? - PullRequest
6 голосов
/ 09 февраля 2010

Я занимаюсь разработкой блогового приложения для некоммерческих организаций. Я хочу, чтобы каждая организация могла изменять свои настройки блога. Я взял шаблон синглтона (из BlogEngine.net) и изменил его. (Я понимаю, что это уже не одноэлементный шаблон.) Я проверил этот подход, и, похоже, он отлично работает в среде разработки. Является ли эта модель хорошей практикой? Существуют ли проблемы, которые могут возникнуть при размещении в производственной среде?

public class UserBlogSettings
    {
    private UserBlogSettings()
    {
        Load();
    }

    public static UserBlogSettings Instance
    {
            get
            {
                string cacheKey = "UserBlogSettings-" + HttpContext.Current.Session["userOrgName"].ToString();
                object cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
                if (cacheItem == null)
                {
                    cacheItem = new UserBlogSettings();
                    HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, DateTime.Now.AddMinutes(1),
                                             Cache.NoSlidingExpiration);
                }
                return (UserBlogSettings) cacheItem;
            }
    }
}    

(части кода для краткости опущены.)

Спасибо за любую помощь, комментарии и т. Д.

Ответы [ 3 ]

5 голосов
/ 09 февраля 2010

Если это за сеанс, сохраните его в сеансе, а не в кэше.

Кроме того, вы беспричинно и неприемлемы здесь:

object cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;

это удаляет ненужные приведения

UserBlogSettings cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
if (cacheItem == null)
{
    cacheItem = new UserBlogSettings();
    HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, 
                         DateTime.Now.AddMinutes(1),
                         Cache.NoSlidingExpiration);
}
return cacheItem;
3 голосов
/ 10 февраля 2010

Вам необходимо использовать блокировку, чтобы избежать возможных условий гонки:

    private static Object lock_Instance = new Object ();
    public static UserBlogSettings Instance 
    { 
        get 
        { 
            string cacheKey = "UserBlogSettings-" + HttpContext.Current.Session["userOrgName"].ToString(); 
            UserBlogSettings cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
            if (cacheItem == null) 
            {
                lock (lock_Instance)
                {
                    // need to check again in case another thread got in here too
                    cacheItem = HttpRuntime.Cache[cacheKey] as UserBlogSettings;
                    if (cacheItem == null)
                    {
                        cacheItem = new UserBlogSettings();
                        HttpRuntime.Cache.Insert(cacheKey, cacheItem, null, 
                            DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration);
                    }
                }
            } 
            return cacheItem; 
        } 
    } 
0 голосов
/ 09 февраля 2010

Я думаю, что в целом у вас все хорошо, но я бы посоветовал повысить производительность, если в этом возникнет необходимость (я знаю ... не оптимизируйте, пока вам действительно не нужно).

Я бы, вероятно, реализовал это с помощью метода, подобного этому, чтобы получить объект настроек:

public static UserBlogSettings getSettings(string orgName, Cache cache) {
  // do the same stuff here, except using the method parameters
}

Причиной этого является то, что HttpContext.Current и HttpRuntime.Cache должны пройти через несколько кругов, чтобы получить дескрипторы текущего сеанса и кэша. Если вы звоните по этому адресу со страницы asp.net, у вас уже есть этот материал под рукой. Поэтому используйте те, которые у вас уже есть, а не ищите их снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...