作者 | |
---|---|
网站 | https://github.com/lsauer/csharp-singleton |
执照 | 麻省理工学院许可证 |
当前的 | |
包裹 | PM> Install-Package CSharp.Portable-Singleton |
描述 | 通用,便携式,有记录且易于使用的单例模式实现,以执行和管理单个实例 |
文档 | 完整参考v2.0.0.4 |
Suport |
|
完整版 | nuget | 建造 | Nuget安装 |
---|---|---|---|
csharp.portable-singleton | PM> Install-Package CSharp.Portable-Singleton |
社会的:
请访问此处以获取完整的参考,该参考也包含在Nuget软件包中。
PM> Install-Package CSharp.Portable-Singleton
。using Core.Singleton;
。MySingleton : Singleton<MySingleton>
。在下面找到一个示例,以瞥见实践中代码的样子:
using Core . Singleton ;
public class AClass : Singleton < AClass >
{
// a public parameterless constructor is required
public AClass ( ) { }
public AMethod ( ) { Console . Write ( " Write called " ) ; }
}
AClass . CurrentInstance . AMethod ( ) ;
System . Diagnostics . Debug . Assert ( ReferenceEquals ( new AClass ( ) , AClass . CurrentInstance ,
" Same Instance " ) ;
.NET并非特别强制执行软件设计模式。单例模式在软件中很明显用作创建设计模式,其中只能实例化对象的一个实例,因此通常扩展了单例对单一访问资源的创建或包装的有用性。
创建一个新的单身人士很简单:向通用的Singleton class Singleton<>
宣布预期的单身班的继承。
例如:
internal class MyClass : Singleton < MyClass > {
.. .
}
单身人士的用法示例将是.NET控制台应用程序的改进的控制台包装器,其他典型的情况将在于表现和同步方面所承受的位置。
注意:可以说,在现代平台上运行的大规模应用程序可以求助于对单例的改进解决方案,尤其是通过设计模式的框架支持。
首先,建议遵守以下语法:
namespace MyNamespace {
using Core . Singleton ;
public class MyClass : Singleton < MyClass > { } ;
var somePropertyValue = Singleton < MyClass > . CurrentInstance . SomeProperty ;
// ...and for a method:
var someMethodValue = Singleton < MyClass > . CurrentInstance . Add ( 1 , 2 ) ;
}
还有其他几种方法可以初始化新的Singleton<T>
实例,其中T
是相应的逻辑Singleton类的类型,指的是实现自定义逻辑的类。
Singleton<T>.CurrentInstance
Singleton<T>.Instance
new T()
SingletonAttribute
,例如[Singleton]class T : Singleton<T>{...}
,然后从Singletonmanager
实例调用Initialize()
Activator.CreateInstance(typeof(T));
new T(...)
SingletonManager
(见下文)TypeInfo
扩展方法ToSingleton()
eg typeof(MyClass).GetTypeInfo().ToSingleton()
Examples
以获取代码和案例方案通用Singleton<T>
构造具有以下静态属性,该属性在EnumSingletonProperty.cs
中引用:
[ Description ( " The current or created instance of the singleton " ) ]
CurrentInstance = 1 << 1 ,
[ Description ( " The internally created instance of the singleton " ) ]
Instance = 1 << 2 ,
[ Description ( " Gets whether the singleton of type TClass is initialized " ) ]
Initialized = 1 << 3 ,
[ Description ( " Gets whether the singleton of type TClass is disposed " ) ]
Disposed = 1 << 4 ,
[ Description ( " Gets whether the singleton of type TClass is blocked for handling " ) ]
Blocked = 1 << 5 ,
在特殊情况下,处置是有帮助的,甚至是必要的。请参阅案例的示例。
myobj is ISingleton
typeof(MyClass).GetTypeInfo().IsSingleton()
如果比较类型已经是TypeInfo
实例,则分别省略对GetTypeInfo()
的调用。
(Instance == null)
是否以下属性遵循INotifyPropertyChanged
的约定,但不实施,同时使用自定义的SingletonPropertyEventHandler
而不是Cannonical PropertyChangedEventHandler
。
事件PropertyChanged
本身被宣布为静态的,即使单身实例本身被处置并免费用于垃圾收集,也可以聆听Disposed
和Initialized
。
public static event SingletonEventHandler PropertyChanged ;
此外,当属性Manager
更改时会触发事件。此属性用于实现ISingletonManager
SingletonManager实例的设置依赖项注入。
如果给定项目中的几个Singleton课程,建议使用并传递SingletonManager
实例。
例如,在关闭或退出应用程序期间,要收听用于清洁后任务的Disposed
事件,可以使用类似的代码样本,如下所示:
Singleton < MyClass > . PropertyChanged += ( sender , arg ) => {
if ( arg . Property == SingletonProperty . Disposed ) {
.. .
}
.. .
} ;
//... prep the application until it is sensible to init the singleton
var logger = Singleton < RenderLogger > . GetInstance ( ) ;
请注意,此时甚至不必初始化单身人士,因此可以安全地将典型的IStream
元素插入单元构建器中。
PropertyChanged
的EventHandler将ISingleton
的实例作为第一个参数,而第二个参数是SingletonPropertyEventArgs
的实例,其中包含以下属性:
Name
:包含更改属性名称的字符串Value
:属性的盒装电流值Property
:该属性编码为SingletonProperty
的枚举值以下代码摘录创建了一个新的SingletonPropertyEventArgs
实例:
var propertyName = SingletonProperty . Instance . ToString ( ) ;
var propertyValue = 100 ;
var args = new SingletonPropertyEventArgs ( SingletonProperty . Initialized , propertyValue ) ;
下面的示例演示了在事件Handler中GetValue
的动态使用,以访问直到运行时才知道的Singleton属性。
Singelton < MyClass > . PropertyChanged += ( sender , arg ) =>
{
if ( arg . Property == SingletonProperty . Initialized )
{
var value = sender . GetValue ( " Value " ) ;
}
} ;
通常,建议通过自定义接口(即ISingletonTemplate<TCommonDenominator>
)使用类似单元子的ACCS属性,并使用is
Operator与显式铸造一起执行特定的Typechecks:
Singelton < MyClass > . PropertyChanged += ( sender , arg ) =>
{
if ( arg . Property == SingletonProperty . Initialized )
{
if ( sender is MyClass /*check including inherited types*/ ) {
var senderTyped = sender as MyClass ;
senderTyped . SetDateTime ( DateTime . Now ) ;
} else if ( sender . GetType ( ) == typeof ( MyStrictClass ) /*check excluding inherited types*/ ) {
var senderTyped = sender as MyStrictClass ;
Console . WriteLine ( senderTyped . SayHello ( ) ) ;
} else {
return ;
}
// do something else if the type got matched
}
} ;
在下面的示例中, AClass
会实现“ Singleton Business Logic”,并从Singleton<>
继承。
包括组件,命名空间和派生就足够了: Singleton<AClass>
获得预期的,经过测试的行为:
using Core . Extensions .
public class AClass : Singleton < AClass >
{
public string AMethod ( [ CallerMemberName ] string caller = " " )
{
return caller ;
}
public static string AStaticMethod ( [ CallerMemberName ] string caller = " " )
{
return caller ;
}
}
static void Main ( string [ ] args )
{
Console . WriteLine ( " Running: " + typeof ( Program ) . Namespace + " . Press any key to quit... " ) ;
var aClass = new AClass ( ) ;
Console . WriteLine ( " Expected: 'Main'; Observed: '{0}' " , aClass . AMethod ( ) ) ;
Console . WriteLine ( " Expected: 'Main'; Observed: '{0}' " , AClass . CurrentInstance . AMethod ( ) ) ;
Console . WriteLine ( " Expected: 'Main'; Observed: '{0}' " , AClass . AStaticMethod ( ) ) ;
object bClass = null ;
try
{
bClass = new AClass ( ) ;
}
catch ( SingletonException exc )
{
if ( exc . Cause == SingletonCause . InstanceExists )
bClass = AClass . CurrentInstance ;
}
var condition = Object . ReferenceEquals ( aClass , bClass ) ;
//> true
var input = Console . ReadKey ( true ) ;
}
注意:在示例文件夹中提供了更多示例。
上面的示例将产生预期的结果:
Running: Examples.Example1. Press any key to quit...
Expected: ' Main ' ; Observed: ' Main '
Expected: ' Main ' ; Observed: ' Main '
Expected: ' Main ' ; Observed: ' Main '
单身班可以抛出SingletonException
(见图1)。
这些在EnumSingletonCause.cs
中引用。
[ Description ( " Indicates the default or unspecified value " ) ]
Unknown = 1 << 0 ,
[ Description ( " Indicates an existing Singleton instance of the singleton class `T` " ) ]
InstanceExists = 1 << 1 ,
[ Description ( " Indicates that the created Singleton instance does not have a parent class " ) ]
NoInheritance = 1 << 2 ,
[ Description ( " Indicates that an exception by another class or module was caught " ) ]
InternalException = 1 << 3 ,
[ Description ( " Indicates that the Singleton must not be instanced lazily through an Acccessor, but the instance explcitely declared in the source-code " ) ]
NoCreateInternal = 1 << 4 ,
[ Description ( " Indicates that the Singleton must not be disposed " ) ]
NoDispose = 1 << 5 ,
[ Description ( " Indicates an existing mismatch between the singleton class `T` and the logical singleton class or parent-class invoking the constructor " ) ]
InstanceExistsMismatch = 1 << 6 ,
对于全局初始化和收缩,单身人士的目的,应始终将[Singleton]
始终归因于以下代码示例:
[ Singleton ( disposable : false , initByAttribute : false , createInternal : true ) ]
public class AClass : Singleton < AClas > {
.. .
}
该属性具有三个可访问的属性:
Disposable
(默认值= false):设置为true
如果允许处置CreateInternal
(default = true):设置为false
,如果仅应该通过用户源代码中的明确声明对singleton进行实例化,则设置为falseInitByAttribute
(default = true):设置为true
以允许通过SingletonManager
方法初始化联合Initialize
要在整个大型应用程序中管理几种单身类型和实例,请使用SingletonManager
类,如下:
下面的示例在单身Pool
迭代,并执行逻辑,取决于单例的类型:
var singletonTypes = new List<Type>() { typeof(ParentOfParentOfAClass), typeof(ParentOfAClass), typeof(IndispensibleClass) };
// create the singletons and add them to the manager
var singletonManager = new SingletonManager(singletonTypes);
foreach (var singleton in singletonManager.Pool)
{
if (singleton.Value is ParentOfParentOfAClass)
{
var instanceTyped = singleton.Value as ParentOfParentOfAClass;
Console.WriteLine($"POPOAClass ImplementsLogic: {instanceTyped.ImplementsLogic}");
} else {
Console.WriteLine(singleton.Value.GetType().FullName);
}
}
singletonManager.Pool
属性提供了对线程安全, ConcurrentDictionary<Type, ISingleton>
实例的访问,该实例允许在熟悉的linq语法中编写查询。
无删除的单例从未删除,但使用SingletonManager的AddOrUpdate
方法设置为null
。
为了创建已知类型的新实例,请使用“通用createInstance方法”,如下所示:
var singletonManager = new SingletonManager ( ) ;
var gameStatics = singletonManager . CreateSingleton < GameStatics > ( ) ;
如果该类型仅在运行时知道或可用的类型作为参数将类型传递为参数,如以下代码示例所示:
var singletonManager = new SingletonManager ( ) ;
var getInstance = ( type ) => {
var gameStatics = singletonManager . CreateSingleton ( type ) ;
} ;
getInstance ( typeof ( GameStatics ) ) ;
Singleton类本身中没有什么可以阻止序列化器的实现,但是开发人员手中的实施和测试。
不建议使用通用解决方案,而是在必要时对这些单身人士进行特定的,经过测试的实现。例如,在休眠 /简历状态方案中。建议将SingletonManager用于此目的。
还要看这个讨论
该库已通过Xunit测试框架进行了测试。测试由几个类进行,其中一类AClass
遵守直接的炮弹遗传模式:
图1:
如果您确定自己遇到了一个错误,请在此处推出新问题。
在几个类的嵌套继承场景中,彼此之间相互继承,并且确定的基类衍生自singleton,定义逻辑Singleton类很重要。这是旨在实现单个职责后实现单个逻辑的类。
它也是确定基类的通用类型T
的类 - Singleton<T>
本身短的类,必须继承Singleton<T>
有关更复杂的继承单程方案,请参考README_Example_Advanced.md
使用此库时保持良好的可读性:
singleton<T>
:例如, ParentOfParentOfAClass.Instance
AClass.Instance
SingletonAttribute
,根据Singleton的目的将单身班属于单身顿类