Return singleton instances of descendants

2020-03-04 10:29发布

问题:

I have a couple of classes that are singletons so I tried to create a parent BaseClass with method GetInstance(params) and derived classes, that should implement this method and return instances of theiselfs (so I dont have to cast them)... as they are singletons the method should be static, but its not allowed to override static methods. What would be the best approach to code it? sample code what i wanted:

  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;
    }
  }

in the code outside of this i want to call

Derived.GetInstance().SomeDerivedMethod()

not

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

I know this is not good, and i have lack of experience with the T type too, so any advices are welcomed. thanks

EDIT:

Or if it is possible somehow define the GetInstance() method in Base, so the derived class does not need to ovwerride it, but it will return the instance of class from where it was called... Derived.GetInstance() will return instance of Derived

回答1:

You could use a Dictionary<Type, Object> for your singletones. The method below requires each type to implement the constructor private. Of course you could also make a check in each of the derived classes if there is already a instance of the class in the singletones dictionary. This would even avoid somebody to use the Activator to create a instance.

Not tested:

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;
        }
    }
}


回答2:

Try the Abstract Factory design pattern. Maybe other creational design patterns may fit too.

You need to enforce the "singleton-ness" on factory level, and then the call may look like:

FooFactory.GetBarInstance().SomeDerivedMethod();


回答3:

its not an real answer but maybe its nice to know anyway. Lazy



回答4:

Why not simply declare the method as non-generic and use the derived type directly:

public class Derived {
  Derived instance;

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