【问题标题】:Return singleton instances of descendants返回后代的单例实例
【发布时间】:2012-01-23 12:31:19
【问题描述】:

我有几个单例类,所以我尝试使用 GetInstance(params) 方法和派生类创建一个父 BaseClass,它们应该实现此方法并返回它们自己的实例(所以我不必强制转换它们)。 ..因为它们是单例,所以方法应该是静态的,但不允许覆盖静态方法。编码它的最佳方法是什么?我想要的示例代码:

  public class Base {

    public static virtual T GetInstance<T>() where T : class;
  }


  public class Derived {
    Derived instance;

    public static override T GetInstance<T>() where T : typeOf(this){
      if (instance == null) {
        instance = new Derived();
        }
      return instance;
    }
  }

在我想调用的代码之外

Derived.GetInstance().SomeDerivedMethod()

不是

(Derived.GetInstance() as Derived).SomeDerivedMethod() and not
new Derived().getInstance().SomeDerivedMethod()

我知道这不好,而且我对T型也缺乏经验,所以欢迎任何建议。 谢谢

编辑:

或者如果有可能以某种方式在 Base 中定义 GetInstance() 方法,那么派生类不需要覆盖它,但它会从调用它的位置返回类的实例... Derived.GetInstance()将返回 Derived 的实例

【问题讨论】:

  • 这个类应该有什么目的? IoC 容器可能更合适。
  • 我会有更多的单例,因此我想提取创建实例的逻辑,这样从父级继承的静态方法总是可以从调用它的地方返回一个类型的实例(即使它来自后代)
  • 这里有类似的讨论codeguru.com/forum/showthread.php?t=376943,看起来没有办法强迫后代成为单身人士,看起来我想要一些奇怪的东西.. :(

标签: c# inheritance static singleton


【解决方案1】:

您可以使用Dictionary&lt;Type, Object&gt; 作为单音。下面的方法要求每种类型都实现构造函数私有。当然,如果单音字典中已经存在该类的实例,您也可以检查每个派生类。这甚至可以避免有人使用Activator 创建实例。

未测试:

public class Base {
    static Dictionary<Type, Object> _Singletones = new Dictionary<Type, Object>();
    public static T GetInstance<T>() where T : class {
        Type t = typeof(T);
        if (_Singletones.ContainsKey(t))
             return _Singletones[t] as T;
        else {
            // Create instance by calling private constructor and return it
            T result = Activator.CreateInstance(t, true) as T;
            _Singletones.Add(t, result);
            return result;
        }
    }
}

【讨论】:

  • 这没关系,虽然像这样的静态方法应该是线程安全的。
  • 是的,伙计!差不多了...但是我怎么能不是从参数而是从调用类中获取类型,所以我应该调用 Base.GetInstance() = Derived.GetInstance() 而不是 Base.GetInstance()返回 Base 和 Derived.get.. 返回 Derived
  • @Groo 你是对的,但是当你有性能关键代码时(例如多次访问该方法时),这可能会很糟糕。也许使用 2 个字典(交换)会提高性能。
  • @Zavael 我认为这是不可能的。您需要使用Base.GetInstance&lt;Dervied&gt;() 访问它。 (在派生类中工作时没有基础)
  • @Felix:不知道你所说的交换是什么意思。如果需要从不同的线程访问它,它应该是线程安全的,除非所有可能的值在启动时都被实例化并且字典被用作只读(现在没有强制执行)。
【解决方案2】:

试试抽象工厂设计模式。也许其他creational design patterns 也可能适合。

您需要在工厂级别强制执行“单例”,然后调用可能如下所示:

FooFactory.GetBarInstance().SomeDerivedMethod();

【讨论】:

  • @Zavael:这就是它被称为抽象的原因。如果您需要 Foo,请使用 FooFactory。它可以实现一个通用接口,但每个工厂实例化自己的类型。
【解决方案3】:

这不是一个真正的答案,但无论如何也许很高兴知道。 Lazy

【讨论】:

  • +1 感谢lazysingleton1 仔细检查:) lambda 版本我无法使用,因为我没有一个实例,而是一本单例字典
【解决方案4】:

为什么不简单地将方法声明为非泛型并直接使用派生类型:

public class Derived {
  Derived instance;

  public static Derived GetInstance() {
    if (instance == null) {
      instance = new Derived();
    }
    return instance;
  }
}

【讨论】:

  • 是的,这是一种方式。我想强制任何派生类通过父 Base 实现单例方法 GetInstance()..
  • 不能在 C# 中强制实现静态方法
  • 是的,我知道,这就是我寻求建议的原因,如果有可能实现我想要的:)
  • @Zavael - 这取决于。使用静态方法实现单例的教科书是不可能的。但是一个更好的强制单例的方法是使用 IoC 并让容器管理实例的生命周期。在大多数框架中,声明给定类的所有子类都具有单例生命周期应该是微不足道的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多