我有两个问题。一个是我正在尝试一个抽象的单例类,它具有单例功能+一些额外的功能,但这个类也是通用的(与单例无关)。我希望它的任何子类都能在不重写代码的情况下继承单例功能,还需要依赖于泛型类型的其余功能。
第二个问题,抽象类有一个非默认的构造函数,它应该接收一个字符串值。该字符串可以由子类的类(继承抽象calss的类)确定。
我的想法如下处理:
T.GetTheString()
作为参数传递给构造函数。不可能,因为接口可能没有静态方法。有什么想法吗?
以下是一些解释我问题的简化代码:
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();
}
}
请注意,我需要GetClassName()
的泛型T,并注意要创建单例的实例,我需要调用继承此类的子类的静态方法(这似乎是不可能的)
编辑:更新了问题以更好地反映我的问题。
编辑:感谢大家的帮助。第二个问题的解决方案是使用默认构造函数,并从子类的非静态方法(基类中的抽象)中获取构造函数中应该是参数的字符串。
另外,我对Singleton继承的整个想法都是错误的,由于Rob Lyndon的回答,我设法解决了这个问题。
这是最终的代码(我知道它没有意义,这只是一个简化的版本......):
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();
}
孩子班:
public sealed class MyNamedObject : NamedObject<MyNamedObject, MyClass>
{
public MyNamedObject() : base() {
}
protected override string GetObjectName () {
return "MyName";
}
}
因此,第一次调用MyNamedObject.Instance
时,它将NamedObject()
构造函数,MyClass
为T
,objectName
参数将为{{} 1}}由子类"MyName"
定义。
正是我在寻找的东西。感谢大家的帮助,这非常有帮助。
答案 0 :(得分:2)
我建议你介绍一个用你装饰每种类型的属性,并在需要时提取它。您将无法在编译时验证类型具有正确的类型,但是您无法做很多事情。单元测试您需要的所有类型:)
[AttributeUsage(AttributeTargets.Class)]
public class NameAttribute : Attribute
{
public NameAttribute(string name)
{
this.Name = name;
}
public string Name { get; set; }
}
[Name("Foo")]
public class SomeClass
{
}
然后在你的单例类中,使用静态构造函数而不是线程不安全的属性。
private static readonly NamedObject<T> instance;
static NamedObject()
{
// TODO: Validation :)
var attributes = typeof(T).GetCustomAttributes(typeof(NameAttribute), false);
var firstAttribute = ((NameAttribute[]) attributes)[0];
string name = firstAttribute.Name;
instance = new NamedObject<T>(name);
}
public static NamedObject<T> Instance { get { return instance; } }
或者使用Lazy<>
代替。有关这方面的更多信息,请参阅my article on singletons。
编辑:澄清 - 你不应该将NamedObject
作为抽象类开始。单身人士和继承根本就不混合。 NamedObject<T>
应该是一个密封的类,它具有任何T
的单个实例。它并不强制只创建了T
的一个实例。
答案 1 :(得分:2)
不要做单身人士。如初。
无论如何,这是一种接近你的用例的方法。
// base class
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 { objectName = GetLabel(typeof(T)) };
}
return _instance;
}
}
private string objectName;
public string GetFullName()
{
return objectName + "(" + GetClassName() + ")";
}
protected abstract string GetLabel(Type type);
protected abstract string GetClassName();
}
答案 2 :(得分:0)
这应该做你想要的(Name
属性也可以是一个抽象方法,如果我们使用单例模式,它看起来更好。)
class Program
{
static void Main(string[] args)
{
Console.WriteLine(MyNamedObject.Instance.Name);
}
}
public abstract class NamedObject<T> where T : NamedObject<T>, new()
{
private static T _instance;
public abstract string Name { get; }
public static T Instance
{
get { return _instance ?? (_instance = new T()); }
}
}
public class MyNamedObject : NamedObject<MyNamedObject>
{
public override string Name
{
get { return "My Named Object Name"; }
}
}