简体   繁体   中英

Static Access To Multiple Instance Variable

I have a singleton instance that is referenced throughout the project which works like a charm. It saves me the trouble from having to pass around an instance of the object to every little class in the project. However, now I need to manage multiple instances of the previous setup, which means that the singleton pattern breaks since each instance would need it's own singleton instance.

What options are there to still maintain static access to the singleton? To be more specific, we have our game engine and several components and plugins reference the engine through a static property. Now our server needs to host multiple game instances each having their own engine, which means that on the server side the singleton pattern breaks.

I'm trying to avoid all the classes having the engine in the constructor.

Edit: The engines isn't guaranteed to be running on a unique thread. Each engine has a unique ID that can be used to identify the instance.

This case is where the Singleton pattern breaks down. Having a single place where all of your code could retrieve an instance was convenient, but now you need to keep multiple instances. However, you're right that it's very annoying to pass context instances all the way through the constructor chains of your object tree. One solution to this problem is to use an Inversion of Control framework, like Ninject . It's a bit of a design investment (since it takes some time to get used to using IoC), but it's particularly good at resolving these issues, where you want to use dependency injection (passing your GameEngine to your various classes), but don't want to write a bunch of glue code just to pass the references around.

That said, if you only have a single context like this (ie it's only the GameEngine that's your singleton), then it's probably simplest to just add it to all of your constructors.

The closest thing you might be able to do is use the ThreadStatic attribute on your singleton instance variable. This will maintain static semantics in terms of access, but each thread will have its own instance.

public class ThreadStaticSingleton
{
    [ThreadStatic]
    private static ThreadStaticSingleton instance;

    public static ThreadStaticSingleTon Instance
    {
        get 
        {
            if(instance == null) instance = new ThreadStaticSingleton();

            return instance;
        }
    }
}

That being said, that could very easily not be what you want. If you need to have either multiple threads access the same instance via the static variable or have one thread access different instances by the same variable, then this won't work.

Put another way, this will work if both of the following are true:

  • Each game engine runs on its own thread
  • Each game engine only runs on one thread

Otherwise, you'll likely have to go the factory pattern route, where each engine passes some sort of identifying information (even if it's just this ) to a static function to obtain the instance rather than just using the Instance property.

You could implement a multi-instance singleton, using a Dictionary of singleton objects. Each of your game instances would then need to use a different key.

There are other ways of doing it not using a Singleton, but something like this might work for you (note: I didn't compile or test this, but it might give you a start).

public class MySingleton
{
    private static Dictionary<string, MySingleton> myInstances = new Dictionary<string, MySingleton>();

    private MySingleton()
    {
        // construct instance
    }

    // note: could also implement using an indexer
    // also note: this is not thread-safe, but you could add a lock around it
    public static MySingleton GetInstance(string key)
    {
        if (!myInstances.ContainsKey(key))
        {
            myInstances.Add(key, new MySingleton());
        }
        return myInstances[key];
    }

    // other methods
}

I'm not 100% sure I've understood the question, but your use of the term 'instance' seems to suggest that each object instance of the singleton must be used by exactly one object instance of a client class. In which case, I'd say just retrieve the singleton instance once per client instance and store in a member variable.

However, it sounds like you don't want to add code to each client class, in which case I don't think there is a way to make the singleton determine which instance to return as the singleton can't know what's calling it (short of some crazy trickery with the thread's call stack).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM