Истекающий экземпляр Singleton после определенного периода времени - PullRequest
2 голосов
/ 17 сентября 2009

Оставляя пока в стороне аргументы об относительных достоинствах и несоответствиях шаблона Singleton, и учитывая, что Singleton обычно считается экземпляром, который сохраняется в течение всей жизни приложения, что было бы наилучшим способом Вы хотите иметь синглтон с ограниченной жизнью?

Что-то не так с чем-то вроде следующего:

public class CategoryHandler
{    

    private static DateTime m_expires;

    public bool HasExpired
    {
        get return DateTime.Now > m_expires;
    }

    private CategoryHandler()
    {
        m_expires = DateTime.Now.AddMinutes(60);
    }

    public static CategoryHandler Instance()
    {
        if(HasExpired)
        {
            //Dispose and reconstruct
        }
        else
        {
            //Use existing instance
        }
    }

}

Или есть гораздо лучший способ решения этой проблемы?

Ответы [ 5 ]

4 голосов
/ 17 сентября 2009

Для обеспечения безопасности потоков вам понадобится какая-то блокировка:

2 голосов
/ 17 сентября 2009

Чтобы избежать проблем с классами, имеющими ссылки на старый экземпляр, вы можете написать кеширующую оболочку для вашего класса. Сначала извлеките интерфейс ICategoryHandler, предположим, он выглядит так:

interface ICategoryHandler 
{
  int A();
}

и затем вы реализуете оболочку (блокировка опущена):

class CategoryHandlerWrapper : ICategoryHandler
{
  ICategoryHandler instance;
  private DateTime expiry = DateTime.MinValue;

  public int A()
  {
    return Instance().A();
  }

  public bool HasExpired
    {
        get return DateTime.Now > expiry;
    }

  private CategoryHandler Instance()
    {
        if(HasExpired)
        {
            //Dispose and reconstruct
        }
        else
        {
            //Use existing instance
        }
    }
}

Таким образом, вы можете использовать обычную инъекцию зависимостей и при этом пользоваться функцией, которую вы ищете. Также проблема со старыми ссылками заключена в одном месте.

2 голосов
/ 17 сентября 2009

Единственная серьезная проблема, которую я вижу, состоит в том, что другой класс уже имеет ссылку на старый экземпляр, это не сделает его недействительным. Так что, пока все классы делают это:

CategoryHandler.Instance.Method();

вместо

CategoryHandler singleton = CategoryHandler.Instance;
...
singleton.SomeMethod();

с вами все будет в порядке, если вы счастливы, что синглтон истечет в следующий раз, когда на него будут ссылаться, а не через шестьдесят минут.

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

1 голос
/ 17 сентября 2009

Рассматривали ли вы возможность использования Контейнера IoC / DI Container и управления им в течение срока службы "синглтона"?

Microsoft Unity - это тот, с которым я больше всего знаком, и они не предоставляют LifetimeManager из коробки, который делает именно то, что вы хотите. Тем не менее, вы можете создать свой собственный потомок; см. Написание пользовательских Lifetime Manager .

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

РЕДАКТИРОВАТЬ: обратите внимание, что это все равно не поможет вам избавиться от «захваченной» проблемы, о которой говорил Мартин.

0 голосов
/ 17 сентября 2009

Чего именно вы хотите достичь с истекающим синглтоном? Я думаю, что у вас есть проблемы с вашим дизайном, если вы действительно хотите это сделать. И, как сказал Мартин, у вас возникнут проблемы, если какой-то код «захватит» ваш синглтонный экземпляр.

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

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