C# 通用单例<;T>;
我有一个问题,这是制作通用单例的正确方法吗C# 通用单例<;T>;,c#,oop,design-patterns,singleton,C#,Oop,Design Patterns,Singleton,我有一个问题,这是制作通用单例的正确方法吗 public class Singleton<T> where T : class, new() { private static T instance = null; private Singleton() { } public static T Instancia { get {
public class Singleton<T> where T : class, new()
{
private static T instance = null;
private Singleton() { }
public static T Instancia
{
get
{
if (instance == null)
instance = new T();
return instance;
}
}
}
公共类单例,其中T:class,new()
{
私有静态T实例=null;
私有单例(){}
公共静态T实例
{
得到
{
if(实例==null)
实例=新的T();
返回实例;
}
}
}
编辑:
在检查一些PDF时,我发现一个通用的单例是以这种方式制作的,这种方式正确吗
public class Singleton<T> where T : class, new()
{
Singleton() { }
class SingletonCreator
{
static SingletonCreator() { }
// Private object instantiated with private constructor
internal static readonly T instance = new T();
}
public static T UniqueInstance
{
get { return SingletonCreator.instance; }
}
}
公共类单例,其中T:class,new()
{
Singleton(){}
类单音创建者
{
静态SingletonCreator(){}
//使用私有构造函数实例化的私有对象
内部静态只读T实例=新T();
}
公共静态T唯一实例
{
获取{return SingletonCreator.instance;}
}
}
通用单例工厂的问题在于,由于它是通用的,因此您无法控制实例化的“单例”类型,因此您永远无法保证您创建的实例将是应用程序中唯一的实例
如果用户可以将类型作为泛型类型参数提供给,则还可以创建该类型的实例。换句话说,<强>您不能创建一个通用的单工厂——它破坏了模式本身。< /强> 对于一个将被重用的通用代码段,您应该在创建单实例的时候考虑线程安全性。p>
实际上,
(instance==null)
可以在单独的线程上计算为true。这是我使用.NET 4的观点
public class Singleton<T> where T : class, new()
{
private Singleton (){}
private static readonly Lazy<T> instance = new Lazy<T>(()=> new T());
public static T Instance { get { return instance.Value; } }
}
公共类单例,其中T:class,new()
{
私有单例(){}
私有静态只读惰性实例=newlazy(()=>newt());
公共静态T实例{get{return Instance.Value;}}
}
使用模式:
var journalSingleton = Singleton<JournalClass>.Instance;
var journalSingleton=Singleton.Instance;
以下是我使用非公共构造函数的实现。现在唯一的问题是没有办法对C#泛型进行自定义约束,因此我必须为具有公共默认构造函数的派生类抛出运行时异常,而不是编译时错误
using System;
using System.Reflection;
using System.Threading;
/// <summary>
/// A generic abstract implementation of the Singleton design pattern (http://en.wikipedia.org/wiki/Singleton_pattern).
///
/// Derived type must contain a non-public default constructor to satisfy the rules of the Singleton Pattern.
/// If no matching constructor is found, an exception will be thrown at run-time. I am working on a StyleCop
/// constraint that will throw a compile-time error in the future.
///
/// Example Usage (C#):
///
/// class MySingleton : Singleton<MySingleton>
/// {
/// private const string HelloWorldMessage = "Hello World - from MySingleton";
///
/// public string HelloWorld { get; private set; }
///
/// // Note: *** Private Constructor ***
/// private MySingleton()
/// {
/// // Set default message here.
/// HelloWorld = HelloWorldMessage;
/// }
/// }
///
/// class Program
/// {
/// static void Main()
/// {
/// var mySingleton = MySingleton.Instance;
/// Console.WriteLine(mySingleton.HelloWorld);
/// Console.ReadKey();
/// }
/// }
/// </summary>
/// <typeparam name="T">Type of derived Singleton object (i.e. class MySingletone: Singleton<MySingleton>).</typeparam>
public abstract class Singleton<T> where T : class
{
/// <summary>
/// "_instance" is the meat of the Singleton<T> base-class, as it both holds the instance
/// pointer and the reflection based factory class used by Lazy<T> for instantiation.
///
/// Lazy<T>.ctor(Func<T> valueFactory,LazyThreadSafetyMode mode), valueFactory:
///
/// Due to the fact Lazy<T> cannot access a singleton's (non-public) default constructor and
/// there is no "non-public default constructor required" constraint available for C#
/// generic types, Lazy<T>'s valueFactory Lambda uses reflection to create the instance.
///
/// Lazy<T>.ctor(Func<T> valueFactory,LazyThreadSafetyMode mode), mode:
///
/// Explanation of selected mode (ExecutionAndPublication) is from MSDN.
///
/// Locks are used to ensure that only a single thread can initialize a Lazy<T> instance
/// in a thread-safe manner. If the initialization method (or the default constructor, if
/// there is no initialization method) uses locks internally, deadlocks can occur. If you
/// use a Lazy<T> constructor that specifies an initialization method (valueFactory parameter),
/// and if that initialization method throws an exception (or fails to handle an exception) the
/// first time you call the Lazy<T>.Value property, then the exception is cached and thrown
/// again on subsequent calls to the Lazy<T>.Value property. If you use a Lazy<T>
/// constructor that does not specify an initialization method, exceptions that are thrown by
/// the default constructor for T are not cached. In that case, a subsequent call to the
/// Lazy<T>.Value property might successfully initialize the Lazy<T> instance. If the
/// initialization method recursively accesses the Value property of the Lazy<T> instance,
/// an InvalidOperationException is thrown.
///
/// </summary>
private static readonly Lazy<T> _instance = new Lazy<T>(() =>
{
// Get non-public constructors for T.
var ctors = typeof (T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
// If we can't find the right type of construcor, throw an exception.
if (!Array.Exists(ctors, (ci) => ci.GetParameters().Length == 0))
{
throw new ConstructorNotFoundException("Non-public ctor() note found.");
}
// Get reference to default non-public constructor.
var ctor = Array.Find(ctors, (ci) => ci.GetParameters().Length == 0);
// Invoke constructor and return resulting object.
return ctor.Invoke(new object[] {}) as T;
}, LazyThreadSafetyMode.ExecutionAndPublication);
/// <summary>
/// Singleton instance access property.
/// </summary>
public static T Instance
{
get { return _instance.Value; }
}
}
/// <summary>
/// Exception thrown by Singleton<T> when derived type does not contain a non-public default constructor.
/// </summary>
public class ConstructorNotFoundException : Exception
{
private const string ConstructorNotFoundMessage = "Singleton<T> derived types require a non-public default constructor.";
public ConstructorNotFoundException() : base(ConstructorNotFoundMessage) { }
public ConstructorNotFoundException(string auxMessage) : base(String.Format("{0} - {1}", ConstructorNotFoundMessage, auxMessage)) { }
public ConstructorNotFoundException(string auxMessage, Exception inner) : base(String.Format("{0} - {1}", ConstructorNotFoundMessage, auxMessage), inner) { }
}
使用系统;
运用系统反思;
使用系统线程;
///
///Singleton设计模式的通用抽象实现(http://en.wikipedia.org/wiki/Singleton_pattern).
///
///派生类型必须包含非公共的默认构造函数,以满足单例模式的规则。
///如果找不到匹配的构造函数,将在运行时引发异常。我在做一个时尚警察
///约束,该约束将在将来引发编译时错误。
///
///用法示例(C#):
///
///类MySingleton:SingletonMySingleton
/// {
///private const string HelloWorldMessage=“Hello World-来自MySingleton”;
///
///公共字符串HelloWorld{get;private set;}
///
/////注意:**私有构造函数***
///二等兵迈辛格尔顿()
/// {
/////在此处设置默认消息。
///HelloWorld=HelloWorldMessage;
/// }
/// }
///
///班级计划
/// {
///静态void Main()
/// {
///var mySingleton=mySingleton.Instance;
///Console.WriteLine(mySingleton.HelloWorld);
///Console.ReadKey();
/// }
/// }
///
///派生的单例对象的类型(即类MySingletone:SingletonMySingleton)。
公共抽象类单例,其中T:class
{
///
///“_instance”是Singleton基类的核心,因为它都包含实例
///指针和LazyT用于实例化的基于反射的工厂类。
///
///LazyT.ctor(FuncT valueFactory,LazyThreadSafetyMode模式),valueFactory:
///
///由于LazyT无法访问singleton的(非公共)默认构造函数和
///C#没有“非公共默认构造函数必需”约束
///在泛型类型中,LazyT的valueFactory Lambda使用反射创建实例。
///
///LazyT.ctor(函数值工厂,LazyThreadSafetyMode模式),模式:
///
///所选模式(ExecutionAndPublication)的说明来自MSDN。
///
///锁用于确保只有一个线程可以初始化LazyT实例
///以线程安全的方式。如果初始化方法(或默认构造函数,如果
///没有初始化方法)在内部使用锁,可能会发生死锁
///使用LazyT构造函数指定初始化方法(valueFactory参数),
///如果该初始化方法引发异常(或无法处理异常),则
///第一次调用LazyT.Value属性时,将缓存并引发异常
///在后续调用LazyT.Value属性时,如果使用LazyT
///未指定初始化方法的构造函数,以及
///未缓存T的默认构造函数
///Value属性可能会成功初始化LazyT实例
///初始化方法递归访问LazyT实例的Value属性,
///引发InvalidOperationException。
///
///
私有静态只读惰性_实例=新惰性(()=>
{
//为T获取非公共构造函数。
var ctors=typeof(T).getconstructor(BindingFlags.Instance | BindingFlags.NonPublic);
public abstract class BaseLazySingleton<T> where T : class
{
private static readonly Lazy<T> LazyInstance =
new Lazy<T>(CreateInstanceOfT, LazyThreadSafetyMode.ExecutionAndPublication);
#region Properties
public static T Instance
{
get { return LazyInstance.Value; }
}
#endregion
#region Methods
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
protected BaseLazySingleton()
{
}
#endregion
}
public static class Singleton<T>
{
private static readonly object Sync = new object();
public static T GetSingleton(ref T singletonMember, Func<T> initializer)
{
if (singletonMember == null)
{
lock (Sync)
{
if (singletonMember == null)
singletonMember = initializer();
}
}
return singletonMember;
}
}
private static MyType _current;
public static MyType Current = Singleton<MyType>.GetSingleton(ref _current, () => new MyType());
MyType.Current. ...
public abstract class Singleton<T> where T : Singleton<T> {
private const string ErrorMessage = " must have a parameterless constructor and all constructors have to be NonPublic.";
private static T instance = null;
public static T Instance => instance ?? (instance = Create());
protected Singleton() {
//check for public constructors
var pconstr = typeof(T).GetConstructors(BindingFlags.Public | BindingFlags.Instance);
//tell programmer to fix his stuff
if (pconstr.Any())
throw new Exception(typeof(T) + ErrorMessage);
}
private static T Create() {
try {
//get nonpublic constructors
var constructors = typeof(T).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
//make sure there is but 1 and use that
return (T)constructors.Single().Invoke(null);
}
catch {
//tell programmer to fix his stuff
throw new Exception(typeof(T)+ErrorMessage);
}
}
}
using System;
using System.Diagnostics;
namespace Singleton
{
class Program
{
static void Main(string[] args)
{
Something.Instance.SayHello();
}
}
/// <summary>
/// Generic singleton pattern implementation
/// </summary>
public class SingletonImplementation<Implementation, ImplementationInterface>
where Implementation : class, ImplementationInterface, new()
{
private SingletonImplementation() { }
private static Implementation instance = null;
public static ImplementationInterface Instance
{
get
{
// here you can add your singleton stuff, which you don't like to write all the time
if ( instance == null )
{
instance = new Implementation();
}
return instance;
}
}
}
/// <summary>
/// Interface for the concrete singleton
/// </summary>
public interface ISomething
{
void SayHello();
}
/// <summary>
/// Singleton "held" or "wrapper" which provides the instance of the concrete singleton
/// </summary>
public static class Something
{
// No need to define the ctor private, coz you can't do anything wrong or useful with an instance of Something
// private Implementation();
/// <summary>
/// Like common: the static instance to access the concrete singleton
/// </summary>
public static ISomething Instance => SingletonImplementation<ImplementationOfSomething, ISomething>.Instance;
/// <summary>
/// Concrete singleton implementation
/// </summary>
private class ImplementationOfSomething : ISomething
{
// No need to define the ctor private, coz the class is private.
// private Implementation();
public void SayHello()
{
Debug.WriteLine("Hello world.");
}
}
}
}
template < class T>
class singleton
{
private:
static T* _instance;
public:
static T* CreateInstance()
{
if (_instance == 0) _instance = new T;
return _instance;
}
static void Release()
{
if (_instance)
{
delete _instance;
_instance = 0;
}
}
};
template<class T> T* singleton<T>::_instance = 0;