작가 | |
---|---|
웹 사이트 | https://github.com/lsauer/csharp-singleton |
특허 | MIT 라이센스 |
현재의 | |
패키지 | PM> Install-Package CSharp.Portable-Singleton |
설명 | 단일 인스턴스를 시행하고 관리하기 위해 일반적이고 휴대용, 문서화 및 사용하기 쉬운 싱글 톤 패턴 구현 |
선적 서류 비치 | 완전한 참조 v2.0.0.4 |
서명 |
|
정식 버전 | 너겟 | 짓다 | 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<>
.
와 같은:
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<T>.CurrentInstance
또는 Singleton<T>.Instance
new T()
[Singleton]class T : Singleton<T>{...}
와 같은 SingletonAttribute
사용 및 Singletonmanager
인스턴스에서 Initialize()
호출Activator.CreateInstance(typeof(T));
사용new T(...)
로 클래스 T를 InscatingSingletonManager
사용 (아래 참조)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
의 협약을 따르지만이를 구현하지는 않습니다. 대조군 PropertyChangedEventHandler
대신 맞춤형 유형의 SingletonPropertyEventHandler
사용합니다.
싱글 톤 인스턴스 자체가 폐기되어 쓰레기 수집에 무료로 사용되는 경우에도 Disposed
및 Initialized
허용되도록 정적으로 구성된 이벤트 PropertyChanged
자체가 정적으로 선언됩니다.
public static event SingletonEventHandler PropertyChanged ;
또한 부동산 Manager
변경 될 때 이벤트가 트리거됩니다. 이 속성은 ISingletonManager
구현하는 SingletonManager 인스턴스의 Setter 종속성 주입에 사용됩니다.
주어진 프로젝트에서 여러 개의 싱글 톤 클래스의 경우 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
의 이벤트 핸들러는 ISingleton
의 인스턴스를 첫 번째 인수로 전달하고, 두 번째 매개 변수로서 SingletonPropertyEventArgs
의 인스턴스는 다음과 같은 속성을 포함합니다.
Name
: 변경된 속성의 이름을 포함하는 문자열Value
: 부동산의 상자 현재 값Property
: SingletonProperty
의 열거 값으로 인코딩 된 속성 다음 코드 발췌문은 새로운 SingletonPropertyEventArgs
인스턴스를 만듭니다.
var propertyName = SingletonProperty . Instance . ToString ( ) ;
var propertyValue = 100 ;
var args = new SingletonPropertyEventArgs ( SingletonProperty . Initialized , propertyValue ) ;
다음 예는 런타임까지 알려지지 않은 싱글 톤 속성에 액세스하기 위해 이벤트 핸들러 내에서 GetValue
의 동적 사용을 보여줍니다.
Singelton < MyClass > . PropertyChanged += ( sender , arg ) =>
{
if ( arg . Property == SingletonProperty . Initialized )
{
var value = sender . GetValue ( " Value " ) ;
}
} ;
일반적으로 사용자 정의 인터페이스 (예 : ISingletonTemplate<TCommonDenominator>
)를 통해 유사한 싱글 톤의 ACCS 속성에 권장되며 명시 적 캐스트와 함께 is
연산자를 사용하여 특정 타이 테크를 수행합니다.
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
(default = false) : 폐기 할 수있는 경우 true
로 설정CreateInternal
(default = true) : 싱글 톤이 사용자 소스 코드 내에서 명시 적 선언에 의해 외부에서만 인스턴스화되어야하는 경우 false
로 설정InitByAttribute
(default = true) : SingletonManager
메소드에 의한 공동 초기화를 Initialize
하도록 true
로 설정 대규모 응용 프로그램의 여러 싱글 톤 유형 및 인스턴스를 관리하려면 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
속성은 친숙한 LINQ 구문에서 쿼리를 작성할 수있는 스레드-안전, ConcurrentDictionary<Type, ISingleton>
인스턴스에 대한 액세스를 제공합니다.
배치 된 싱글 톤은 결코 삭제되지 않지만 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 ) ) ;
싱글 톤 클래스 자체에는 시리얼 라이저의 구현을 방해하는 것이 없지만 테스트뿐만 아니라 구현은 개발자의 손에 달려 있습니다.
일반 솔루션은 권장되지 않고 필요한 경우 해당 싱글 톤의 구현 된 구현을 권장합니다. 예를 들어 최대 절전 모드 / 이력서 상태 시나리오에서. 그 목적으로 SingletonManager를 확장하는 것이 좋습니다.
또한이 토론을 살펴보십시오
이 라이브러리는 Xunit 테스트 프레임 워크에 의해 테스트되었습니다. 테스트는 여러 클래스로 실행되며, AClass
중 하나는 간단한 대포 상속 스키마에 부착됩니다.
그림 1 : : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 1 : 그림 및 그림 1 : 그림 및 그림 및 그림 1 : 그림 및 그림 1 : 그림 및 그림 및 그림 1 : 그림 및 그림 및 그림 1 : 그림 및 그림 주 및 그림 주 및 그림은 나타내 나타내는 나타내는 나타내는 나타내는 나타내 나타내는 그림들이 나타내 나타내 한 나타내 나타내 나타내는 나타내 나타내 나타내 나타내 나타내 나타내 나타내 나타내 나타내 나타내 나타내 나타내OOO언 나타내 나타내 나타내 나타내 나타내 :
버그에 부딪쳤다 고 확신한다면 새로운 문제를 여기에서 밀어 넣으십시오.
서로 계층 적으로 서로를 물려받는 여러 클래스의 중첩 된 상속 시나리오와 싱글 톤에서 파생 된 결정된 기본 클래스에서 논리적 싱글 톤 클래스를 정의하는 것이 중요합니다. 이것은 단일 책임을 따른 SingleOTN의 논리를 구현하기위한 클래스입니다.
또한 기본 클래스의 일반 유형 T
결정하는 클래스 - Singleton<T>
자체의 클래스는 Singleton<T>
상속해야합니다.
보다 복잡한 상속 싱글 톤 시나리오는 README_Example_Advanced.md
를 참조하십시오.
이 라이브러리를 사용할 때 좋은 가독성을 유지하려면 :
singleton<T>
AClass.Instance
일반 매개 변수로 전달 된 것보다 다른 유형에서 정적 액세서 액세스를 피하십시오 ParentOfParentOfAClass.Instance
SingletonAttribute
사용하여 싱글 톤의 목적에 따라 싱글 톤 클래스에 속합니다.