I've got two problems. One is that I'm trying to have an abstract singleton class, that has the singleton functionality + a little extra functionality in it, but this class is also a generic (unrelated to it being singleton). I want any of it's child classes to inherit the singleton functionality without rewriting code, and also the rest of the functionality which is dependent on the generic type.
Second problem, the abstract class has a non-default constructor, that should receive a string value. This string can be determined by the class of the child-class (the class that inherits the abstract calss).
My ideas to handle this where as follows:
- Add an abstract static method to the abstract class that returns a string parameter, so that every derived class will implement it, hence any non-abstract instance of the class will work fine. Not possible because static methods cannot be abstract.
- Create an interface with a static method that returns the string, and make sure that the generic type inherits from that interface. Then when instantiating the singleton, it will call
T.GetTheString()
to pass as a parameter to the constructor. Not possible since interfaces may not have static methods.
Any ideas?
Here's some simplified code that explains my problem:
public abstract class NamedObject<T> {
private static NamedObject<T> _instance;
public static NamedObject<T> Instance {
get {
if (_instance == null) {
_instance = new NamedObject<T>("Need to determine this string from the non-abstract child class of NamedObject");
}
return _instance;
}
}
private string objectName;
public NamedObject(string objectName) {
this.objectName = objectName;
}
public string GetFullName() {
return objectName + "(" + GetClassName() + ")";
}
protected virtual string GetClassName() {
return typeof(T).ToString();
}
}
Note that I need the generic T for GetClassName()
, and note that to create an instance of the singleton, I need to call a static method of the child class that inherits this class (which seems to be impossible)
Edit: Updated the question to better reflect my problems.
Edit: Thanks for everyone's help. The solution for the second issue was to use a default constructor, and get the string that was supposed to be a parameter within the constructor from a non-static method of the child class (abstract in the base class).
In addition, my entire idea of Singleton inheritance was wrong, which I managed to fix thanks to Rob Lyndon's answer.
Here's the final code (I know it doesn't make sense, this is just a simplified version...):
public abstract class NamedObject<ME, T> where ME : NamedObject<ME, T>, new()
{
private static NamedObject<ME, T> _instance;
public static NamedObject<ME, T> Instance {
get {
if (_instance == null) {
_instance = new ME();
}
return _instance;
}
}
private string objectName = "test";
public NamedObject() {
this.objectName = GetObjectName();
}
public string GetFullName() {
return objectName + "(" + GetClassName() + ")";
}
protected virtual string GetClassName() {
return typeof(T).ToString();
}
protected abstract string GetObjectName();
}
And the child class:
public sealed class MyNamedObject : NamedObject<MyNamedObject, MyClass>
{
public MyNamedObject() : base() {
}
protected override string GetObjectName () {
return "MyName";
}
}
So when calling MyNamedObject.Instance
for the first time, it will NamedObject()
constructor, with MyClass
as T
, and the objectName
parameter will be "MyName"
as defined by the child class MyNamedObject
.
Exactly what I was looking for. Thanks for everyone's help this was very helpful.