C# 抽象基类,强制每个派生类都是单例的
如何创建一个抽象类,强制每个派生类都是单例的?我使用的C#.不起作用,因为单例需要静态访问,而不能强制访问C# 抽象基类,强制每个派生类都是单例的,c#,oop,ooad,C#,Oop,Ooad,如何创建一个抽象类,强制每个派生类都是单例的?我使用的C#.不起作用,因为单例需要静态访问,而不能强制访问 有关Singleton实现+示例,请参见:Singleton意味着拥有私有构造函数。但是你知道私有成员不能被继承。在C++中有模板,所以可以从模板类创建单体。在C#中,没有模板,因此您必须为所需的每个单例编写自己的私有构造函数。当您想要实施编译时检查时,这是不可能的。通过运行时检查,您可以做到这一点。这并不漂亮,但这是可能的。下面是一个例子: public abstract class S
有关Singleton实现+示例,请参见:Singleton意味着拥有私有构造函数。但是你知道私有成员不能被继承。在C++中有模板,所以可以从模板类创建单体。在C#中,没有模板,因此您必须为所需的每个单例编写自己的私有构造函数。当您想要实施编译时检查时,这是不可能的。通过运行时检查,您可以做到这一点。这并不漂亮,但这是可能的。下面是一个例子:
public abstract class Singleton
{
private static readonly object locker = new object();
private static HashSet<object> registeredTypes = new HashSet<object>();
protected Singleton()
{
lock (locker)
{
if (registeredTypes.Contains(this.GetType()))
{
throw new InvalidOperationException(
"Only one instance can ever be registered.");
}
registeredTypes.Add(this.GetType());
}
}
}
public class Repository : Singleton
{
public static readonly Repository Instance = new Repository();
private Repository()
{
}
}
公共抽象类单例
{
私有静态只读对象锁定器=新对象();
私有静态HashSet registeredTypes=new HashSet();
受保护的单例()
{
锁(储物柜)
{
if(registeredTypes.Contains(this.GetType()))
{
抛出新的InvalidOperationException(
“只能注册一个实例。”);
}
registeredTypes.Add(this.GetType());
}
}
}
公共类存储库:Singleton
{
public static readonly Repository实例=new Repository();
专用存储库()
{
}
}
java或C语言中的类不是“一流的”。类的静态部分不能被子类继承或重写。有关更多详细信息,请参阅。另外,你没有元类的概念
在Smalltalk或Ruby等语言中,您可以定义一个新的元类Singleton
,它定义了一个方法getInstance
。然后可以将ClassA
和ClassB
定义为Singleton
元类的实例。然后这两个类自动公开一个方法getInstance
,该方法可用于创建实例objectA
或objectB
。那不是很酷吗?实际上,你并不经常使用元类,而单例是它们唯一有意义的用法,我知道。这里有一个(丑陋的)方法。它可能会被简化和改进,但这是我第一次尝试
其思想是首先使基类成为一个泛型抽象类(如上面的注释所述),但是类型参数被限制为从基类本身派生。这允许基类处理派生类型的单例实例。注意:所有派生类都应该密封,就像任何单例类一样
接下来,允许使用受保护的构造函数,但需要接受特殊类SingletonKey的实例,该类是一个修改过的singleton。派生类可以访问SingletonKey类定义,但基类保留对唯一允许的实例的私有控制,从而控制所有派生对象的构造
第三,基类需要能够调用派生类的构造函数,但这有点棘手。如果您试图调用派生的键控构造函数,编译器会抱怨,因为它不能保证存在。解决方案是添加派生类必须初始化的静态委托。因此,任何派生类都需要提供一个简单的初始化方法。在代码中首次尝试访问实例之前,应显式调用此初始化方法,否则将导致运行时错误
public abstract class Singleton<T> where T : Singleton<T>
{
protected Singleton(SingletonKey key) { }
private static SingletonKey _key;
private static SingletonKey Key
{
get
{
if (_key == null) SingletonKey.Initialize();
return _key;
}
}
protected class SingletonKey
{
private SingletonKey()
{
}
public static void Initialize()
{
if (_key == null)
{
_key = new SingletonKey();
}
}
}
protected static Func<SingletonKey, T> Creator;
private static T instance;
public static T Instance
{
get
{
if (instance == null) instance = Creator(Key);
return instance;
}
}
}
public class MySingleton : Singleton<MySingleton>
{
public string Name { get; set; }
public static void Initialize()
{
Creator = (key) => new MySingleton(key);
}
protected MySingleton(SingletonKey key) : base(key)
{
}
}
公共抽象类Singleton,其中T:Singleton
{
受保护的单例(单例密钥){}
私有静态单密钥_密钥;
私有静态单密钥
{
得到
{
如果(_key==null)SingletonKey.Initialize();
返回_键;
}
}
保护类单键
{
私有单通密钥()
{
}
公共静态void Initialize()
{
如果(_key==null)
{
_key=新的SingletonKey();
}
}
}
受保护的静态函数创建者;
私有静态T实例;
公共静态T实例
{
得到
{
如果(instance==null)instance=Creator(Key);
返回实例;
}
}
}
公共类MySingleton:Singleton
{
公共字符串名称{get;set;}
公共静态void Initialize()
{
Creator=(key)=>newmysingleton(key);
}
受保护的MySingleton(单键键):基本(键)
{
}
}
我相信我曾试图实现类似的目标,即在一组类上强制实施公共接口和单例模式。这就是我的解决方案:
// Common interface of my singleton classes
public interface IMySingletonClass
{
string ValueGetter();
void ValueSetter(string value);
}
// Generic abstract base class
public abstract class Singleton<T>: IMySingletonClass
{
private static readonly object instanceLock = new object();
private static T instance; // Derived class instance
// Protected constructor accessible from derived class
protected Singleton()
{
}
// Returns the singleton instance of the derived class
public static T GetInstance()
{
lock (instanceLock)
{
if (instance == null)
{
instance = (T)Activator.CreateInstance(typeof(T), true);
}
return instance;
}
}
// IMySingletonClass interface methods
public abstract string ValueGetter();
public abstract void ValueSetter(string value);
}
// Actual singleton class
public class MySingletonClass : Singleton<MySingletonClass>
{
private string myString;
private MySingletonClass()
{
myString = "Initial";
}
public override string ValueGetter()
{
return myString;
}
public override void ValueSetter(string value)
{
myString = value;
}
}
请注意,如果您只需要基本的“模板”,就可以轻松地从通用抽象单例类中删除公共接口。这里是我的单例继承实现:
using System;
using System.Reflection;
namespace Mik.Singleton
{
class Program
{
static void Main()
{
//You can not create an instance of class directly
//Singleton1 singleton1 = new Singleton1();
Singleton1 singleton1 = Singleton1.Instance;
Singleton2 singleton2 = Singleton2.Instance;
Console.WriteLine(singleton1.Singleton1Text);
Console.WriteLine(singleton2.Singleton2Text);
Console.ReadLine();
}
}
public class SingletonBase<T> where T : class
{
#region Singleton implementation
private static readonly object lockObj = new object();
private static T _instance;
protected SingletonBase() { }
public static T Instance
{
get
{
if (_instance == null)
{
lock (lockObj)
{
if (_instance == null)
_instance = CreateInstance();
}
}
return _instance;
}
}
private static T CreateInstance()
{
ConstructorInfo constructor = typeof(T).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null, new Type[0],
new ParameterModifier[0]);
if (constructor == null)
throw new Exception(
$"Target type is missing private or protected no-args constructor: {typeof(T).FullName}");
try
{
T instance = constructor.Invoke(new object[0]) as T;
return instance;
}
catch (Exception e)
{
throw new Exception(
"Failed to create target: type=" + typeof(T).FullName, e);
}
}
#endregion Singleton implementation
}
public class Singleton1 : SingletonBase<Singleton1>
{
private Singleton1() { }
public string Singleton1Text { get; } = "Singleton1Text value";
}
public class Singleton2 : SingletonBase<Singleton2>
{
private Singleton2() { }
public string Singleton2Text { get; } = "Singleton2Text value";
}
}
使用系统;
运用系统反思;
名称空间Mik.Singleton
{
班级计划
{
静态void Main()
{
//不能直接创建类的实例
//Singleton1 Singleton1=新Singleton1();
Singleton1 Singleton1=Singleton1.Instance;
Singleton2 Singleton2=Singleton2.Instance;
Console.WriteLine(singleton1.Singleton1Text);
Console.WriteLine(singleton2.Singleton2Text);
Console.ReadLine();
}
}
公共类单音基,其中T:class
{
#区域单例实现
私有静态只读对象lockObj=新对象();
私有静态T_实例;
受保护的SingletonBase(){}
公共静态T实例
{
得到
{
if(_instance==null)
{
锁(lockObj)
{
if(_instance==null)
_实例
using System;
using System.Reflection;
namespace Mik.Singleton
{
class Program
{
static void Main()
{
//You can not create an instance of class directly
//Singleton1 singleton1 = new Singleton1();
Singleton1 singleton1 = Singleton1.Instance;
Singleton2 singleton2 = Singleton2.Instance;
Console.WriteLine(singleton1.Singleton1Text);
Console.WriteLine(singleton2.Singleton2Text);
Console.ReadLine();
}
}
public class SingletonBase<T> where T : class
{
#region Singleton implementation
private static readonly object lockObj = new object();
private static T _instance;
protected SingletonBase() { }
public static T Instance
{
get
{
if (_instance == null)
{
lock (lockObj)
{
if (_instance == null)
_instance = CreateInstance();
}
}
return _instance;
}
}
private static T CreateInstance()
{
ConstructorInfo constructor = typeof(T).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null, new Type[0],
new ParameterModifier[0]);
if (constructor == null)
throw new Exception(
$"Target type is missing private or protected no-args constructor: {typeof(T).FullName}");
try
{
T instance = constructor.Invoke(new object[0]) as T;
return instance;
}
catch (Exception e)
{
throw new Exception(
"Failed to create target: type=" + typeof(T).FullName, e);
}
}
#endregion Singleton implementation
}
public class Singleton1 : SingletonBase<Singleton1>
{
private Singleton1() { }
public string Singleton1Text { get; } = "Singleton1Text value";
}
public class Singleton2 : SingletonBase<Singleton2>
{
private Singleton2() { }
public string Singleton2Text { get; } = "Singleton2Text value";
}
}