So I'm working on a middleware layer.
I'm consuming a COM DLL that deals with the low level hardware interaction, and providing an interface for the UI to do IO with the hardware.
As part of the design of my layer, we put in a contextmanager that arranges the various pieces of hardware to 开发者_运维问答produce contexts that our application can work with.
So I want to guarantee that a developer that is working with my code has a single context manager to work with and then inside that context manager I can guarantee that we only allocate 1 work queue per hardware device.
Just to complicate this there is some initialization that must be done before I can start adding in hardware devices. Something that would be simple if not for the fact that typically you only access a singleton via a readonly property.
I know the singleton pattern can make alot of things difficult because of it's global accessibility. I really do not want, nor need for this class to have the global availability of a singleton, I just want the guarantee that only one will be created inside the app.
For that would I be crazy to do something like this, to basically give my singleton a constructor:
public class MySingleton
{
private static MySingleton _MySingleton;
private static object singletonLock = new object();
private MySingleton(int foo1, string foo2)
{
//do init stuff
}
public static MySingleton StartSingleton(int foo1, string foo2)
{
try
{
Monitor.Enter(singletonLock);
if (_MySingleton == null)
{
_MySingleton = new MySingleton(foo1, foo2);
}
else
throw new Exception("Singleton already initialized");
}
finally
{
Monitor.Exit(singletonLock);
}
return _MySingleton;
}
public static MySingleton Instance
{
get
{
try
{
Monitor.Enter(singletonLock);
if (_MySingleton == null)
{
throw new Exception("Singleton must be Initialized");
}
}
finally
{
Monitor.Exit(singletonLock);
}
return _MySingleton;
}
}
}
It's not crazy code but it is a singleton anyway. If you remove Instance
property then it won't be singleton anymore.
Global accessibility is not all that makes singletons nasty. What makes them nasty is that they are used all through the system directly without you being able to track all those usages. That's why it is such a nightmare in multi-threading code, that's why it is so hard to unit test anything with singletons inside.
So if it is your code I'd recommend creating just one object during application initialization and pass it around with dependency injection or as plain constructor argument. If it is a library, you can either check in constructor if it is first object being created or not and throw an exception or you can go with static constructor as you did but without Instance
property, forcing developers to pass instance around.
As always, you can just create singleton, after all all it matters is that product works and customers enjoy using it, singletons or no singletons doesn't really matter.
You wouldn't be crazy. A singleton avoids the drawbacks of global variables by virtue of being namespaced. Even though it is globally accessible via a static function call, it is not a global variable. And further, it is accessed via a namespace, so noone is likely to put it in a global var called temp, then later assign something else to temp. They should always get a local reference to it by doing
MySingleton singletonRef = MySingleton.Instance();
when their scope closes, the reference dies, and so it's not a global variable.
So if I just need to garuntee that you can only create one version of my object then something like this would work:
public class MySingleton
{
private static int objectCount = 0;
private static object singletonLock = new object();
public MySingleton(int foo1, string foo2)
{
try{
Monitor.Enter(singletonLock);
if (objectCount != 0)
{
throw new Exception("MySingleton Already exsists");
}
else
{
objectCount++;
}
}
finally{
Monitor.Exit(singletonLock);
}
//do initialization stuff
}
}
obviously not a true singleton anymore.
精彩评论