静态访问多个实例变量

时间:2010-04-15 21:11:38

标签: c# .net static singleton

我有一个在整个项目中引用的单例实例,它就像一个魅力。它使我免于必须将对象的实例传递给项目中的每个小类。但是,现在我需要管理先前设置的多个实例,这意味着单例模式会中断,因为每个实例都需要它自己的单例实例。

还有哪些选项可以保持对单例的静态访问?更具体地说,我们有我们的游戏引擎和几个组件和插件通过静态属性引用引擎。现在我们的服务器需要托管多个游戏实例,每个实例都有自己的引擎,这意味着在服务器端单例模式会中断。

我正在尝试避免构造函数中所有具有引擎的类。

编辑:不保证引擎在唯一的线程上运行。每个引擎都有一个唯一的ID,可用于标识实例。

4 个答案:

答案 0 :(得分:4)

这种情况是Singleton模式崩溃的地方。拥有一个所有代码都可以检索实例的地方很方便,但现在需要保留多个实例。但是,你是对的,将上下文实例一直传递到对象树的构造函数链是非常烦人的。该问题的一个解决方案是使用控制反转框架,如Ninject。这是一个设计投资(因为它需要一些时间来习惯使用IoC),但它特别擅长解决这些问题,你想要使用依赖注入(将你的GameEngine传递给你的各个类),但不要我想写一堆胶水代码只是为了传递参考文献。

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

答案 1 :(得分:3)

您可以做的最接近的事情是在单例实例变量上使用ThreadStatic属性。这将在访问方面保持静态语义,但每个线程都有自己的实例。

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

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

            return instance;
        }
    }
}

话虽这么说,非常很容易就不是你想要的。如果您需要让多个线程通过静态变量访问同一个实例,或者让一个线程通过同一个变量访问不同的实例,那么这将不起作用。

换句话说,如果以下两者为真,则此方法有效:

  • 每个游戏引擎都在自己的线程上运行
  • 每个游戏引擎在一个线程上运行

否则,您可能必须进入工厂模式路由,其中​​每个引擎将某种标识信息(即使它只是this)传递给静态函数以获取实例而不是仅使用Instance财产。

答案 2 :(得分:2)

您可以使用单个对象的Dictionary来实现多实例单例。然后,您的每个游戏实例都需要使用不同的密钥。

还有其他方法可以不使用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
}

答案 3 :(得分:0)

我并不是百分之百确定我已经理解了这个问题,但是你对“实例”一词的使用似乎暗示了单例的每个对象实例必须由客户类的一个对象实例使用。在这种情况下,我会说每个客户端实例只检索一次单例实例并存储在一个成员变量中。

但是,听起来你不想在每个客户端类中添加代码,在这种情况下,我认为没有办法让单例确定要返回哪个实例,因为单例无法知道调用它的是什么(缺少线程调用堆栈的一些疯狂诡计。