Expiry of a Singleton instance after a period of time
Putting aside arguments for the relative virtues and disvirtues of the Singleton pattern so far, and given that a Singleton is generally considered to be an instance that persists for the life of an application, what would be the best way to go about having a Singleton that has a limited life?
Is there anything amiss with something like the following:
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
}
}
}
Or is there a much better way to approach this problem?
source to share
To ensure thread safety, you need some kind of blocking:
public sealed class CategoryHandler
{
private static CategoryHandler _instance = null;
private static DateTime _expiry = DateTime.MinValue;
private static readonly object _lock = new object();
private CategoryHandler() { }
public static bool HasExpired
{
get
{
lock (_lock) { return (_expiry < DateTime.Now); }
}
}
public static CategoryHandler Instance
{
get
{
lock (_lock)
{
if (HasExpired)
{
// dispose and reconstruct _instance
_expiry = DateTime.Now.AddMinutes(60);
}
return _instance;
}
}
}
}
source to share
The only major problem I see is that another class is already referencing the old instance, this will not invalidate it. So while all classes are doing this:
CategoryHandler.Instance.Method();
but not
CategoryHandler singleton = CategoryHandler.Instance;
...
singleton.SomeMethod();
you should be fine if you are happy that the singleton will expire on the next call, and not in sixty minutes.
If you need it to expire exactly after a certain amount of time, you will need to use a timer and replace the instance in the callback method (beware that the timer will callback in another thread, so be sure to implement a thread safe singleton pattern)
source to share
To avoid problems with classes that reference the old instance, you might consider creating a cache wrapper for your class. The fist will retrieve the ICategoryHandler interface, suppose it looks like this:
interface ICategoryHandler
{
int A();
}
and then you implement the wrapper (lock omitted):
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
}
}
}
This way you can use normal dependency injection and still use the function you are using. Also the issue with old links is encapsulated in one place.
source to share
Have you considered using the IoC / DI Container framework and "singleton" lifetime management?
Microsoft Unity is the one I'm most familiar with, and they don't provide a LifetimeManager out of the box, does exactly what you want to do. However, you can create your own child; see Writing Custom Lifecycle Managers .
Or you can look at other structures and see if you have what you want in the box.
EDIT: Please note that this still won't get you out of the "trapped" problem Martin was talking about.
source to share
What exactly do you want to achieve with the expiring single? I think you are in design trouble if you really want to. And as Martin said, you will have problems if some code "hijacks" you in a single instance.
So what exactly do you use for this? Or is it just a question of curiosity?
source to share