作者 | |
---|---|
網站 | 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的目的將單身班屬於單身頓類