简体   繁体   English

静态访问多个实例变量

[英]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. 每个引擎都有一个唯一的ID,可用于标识实例。

This case is where the Singleton pattern breaks down. 这种情况是Singleton模式崩溃的地方。 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 . 该问题的一个解决方案是使用Inversion of Control框架,如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. 这是一个设计投资(因为它需要一些时间来习惯使用IoC),但它特别擅长解决这些问题,你想要使用依赖注入(将你的GameEngine传递给你的各个类),但不要我想写一堆胶水代码只是为了传递参考。

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. 也就是说,如果你只有这样一个上下文(即它只是GameEngine那是你的单身人士),那么将它添加到你的所有构造函数中可能是最简单的。

The closest thing you might be able to do is use the ThreadStatic attribute on your singleton instance variable. 您可能能够做的最接近的事情是使用单例实例变量上的ThreadStatic属性。 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. 否则,您可能必须转到工厂模式路由,其中​​每个引擎将某种标识信息(即使只是this )传递给静态函数以获取实例而不是仅使用Instance属性。

You could implement a multi-instance singleton, using a Dictionary of singleton objects. 您可以使用单个对象的Dictionary来实现多实例单例。 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). 还有其他方法可以不使用Singleton,但这样的东西可能适合你(注意:我没有编译或测试它,但它可能会给你一个开始)。

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. 我并不是100%确定我已经理解了这个问题,但是你对“实例”一词的使用似乎暗示了单例的每个对象实例必须由客户类的一个对象实例使用。 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). 但是,听起来你不想在每个客户端类中添加代码,在这种情况下,我认为没有办法让单例确定要返回哪个实例,因为单例无法知道调用它的是什么(没有线程的调用堆栈的一些疯狂的诡计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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