26 Ekim 2018 Cuma

Stateless

https://github.com/dotnet-state-machine/stateless

Stateless (Durum Bilgisiz / Durumsuz )

Doğrudan .NET kodunda durum makineleri ve hafif durum tabanlı makine tabanlı iş akışları oluşturun:

var phoneCall = new StateMachine<State, Trigger>(State.OffHook);

phoneCall.Configure(State.OffHook)
    .Permit(Trigger.CallDialled, State.Ringing);
 
phoneCall.Configure(State.Ringing)
    .Permit(Trigger.CallConnected, State.Connected);
 
phoneCall.Configure(State.Connected)
    .OnEntry(() => StartCallTimer())
    .OnExit(() => StopCallTimer())
    .Permit(Trigger.LeftMessage, State.OffHook)
    .Permit(Trigger.PlacedOnHold, State.OnHold);

// ...

phoneCall.Fire(Trigger.CallDialled);
Assert.AreEqual(State.Ringing, phoneCall.State);

Yukarıdaki projenin yanı sıra bu proje de Basit Durum Makinesi'nden esinlenmiştir.


Özellikler

Çoğu standart durum makinesi yapıları desteklenir:

  • Herhangi bir .NET türünün durumları ve tetikleyicileri için genel destek (sayılar, dizeler, numaralar vb.)
  • Hiyerarşik durumlar
  • Durumlar için giriş / çıkış olayları
  • Koşullu geçişleri desteklemek için koruma maddeleri
  • İçgözlem
Bazı faydalı uzantılar da sağlanmıştır:
  • Durumu harici olarak depolayabilme (örneğin, bir ORM tarafından izlenen bir özellik)
  • Parametreli tetikleyiciler
  • Yeniden girişli durum
  • DOT grafiğine aktarma

Hiyerarşik Durumlar

Aşağıdaki örnekte, OnHold durumu, Connected durumun bir alt-durumudur. Bu, bir OnHold çağrısının hala bağlı olduğu anlamına gelir.

phoneCall.Configure(State.OnHold)
    .SubstateOf(State.Connected)
    .Permit(Trigger.TakenOffHold, State.Connected)
    .Permit(Trigger.PhoneHurledAgainstWall, State.PhoneDestroyed);

StateMachine.State özelliğine ek olarak, kesin mevcut durumu bildirecek olan bir IsInState (State) yöntemi sağlanmıştır. IsInState (State) alt durumları dikkate alacaktır, böylece yukarıdaki örnek OnHold durumundaysa, IsInState (State.Connected) da true olarak değerlendirilecektir.


Durumlar İçin Giriş/Çıkış Olayları

Örnekte, bir çağrı bağlandığında StartCallTimer () metotu çalıştırılacaktır. Çağrı tamamlandığında StopCallTimer () çalıştırılacaktır.

Çağrı, OnHold durumunun Connected durumun bir durumu olduğu için tekrar tekrar çağrılan StartCallTimer () ve StopCallTimer () metotları kullanılmadan Connected ve OnHold durumları arasında hareket edebilir.

Giriş / Çıkış olay işleyicileri, tetikleyici, kaynak ve hedef durumları açıklayan bir Transition türü parametresi ile birlikte sağlanabilir.

Dış Durum Depolama

Durum Bilgisiz, çeşitli uygulama modellerine gömülecek şekilde tasarlanmıştır. Örneğin, bazı ORM'ler eşlenmiş verilerin nerede depolanabileceğine dair gereksinimleri yerine getirir ve UI çerçeveler genellikle özel "bağlanabilir" özelliklerinde depolanmak üzere durum gerektirir.Bu amaçla, StateMachine yapıcısı, durum değerlerini okumak ve yazmak için kullanılacak işlev argümanlarını kabul edebilir:

var stateMachine = new StateMachine<State, Trigger>(
    () => myState.Value,
    s => myState.Value = s);

Bu örnekte durum makinesi, durum depolama için myState nesnesini kullanacaktır.

Başka bir örnek, örnek klasörde bulunan JsonExample çözümünde bulunabilir.

İçgözlem

Durum makinesi, tetikleyicilerin bir listesini, StateMachine.PermittedTriggers özelliği aracılığıyla geçerli durumda başarılı bir şekilde tetiklenebilen bir liste sağlayabilir. Durum yapılandırması hakkında bilgi almak için StateMachine.GetInfo () metotudunu kullanın.

Güvenlik maddeleri

Durum makinesi, koruma maddelerine dayalı çoklu geçişler arasında seçim yapar;
phoneCall.Configure(State.OffHook)
    .PermitIf(Trigger.CallDialled, State.Ringing, () => IsValidNumber)
    .PermitIf(Trigger.CallDialled, State.Beeping, () => !IsValidNumber);

Bir durum içindeki güvenlik maddelerinin karşılıklı olarak özel olması şarttır (aynı anda birden fazla güvenlik maddesi geçerli olamaz). Alt durumlar bunları tekrar belirterek geçişleri geçersiz kılar, ancak alt durumlar, üst-durumlar (superstate) tarafından izin verilerin geçişlere izin veremez.

Bir tetikleyici tetiklendiğinde koruma maddeleri değerlendirilecektir. Güvenlikler, yan etkisiz hale getirilmelidir.


Parametreli tetikleyiciler

Güçlü yazılan(Strongly-typed) parametreler tetikleyicilere atanabilir:

var assignTrigger = stateMachine.SetTriggerParameters<string>(Trigger.Assign);

stateMachine.Configure(State.Assigned)
    .OnEntryFrom(assignTrigger, email => OnAssigned(email));

stateMachine.Fire(assignTrigger, "joe@example.com");

Tetik parametreleri, PermitDynamic () yapılandırma metodunu kullanarak hedef durumu dinamik olarak seçmek için kullanılabilir.


Gözardı Edilen Geçişler ve Yeniden Girişli Durumlar

Bununla ilişkili izin verilen bir geçişi olmayan bir tetikleyici tetiklemek, bir istisnanın atılmasına neden olur.

Belirli durumlar içinde tetikleyicileri yok saymak için Ignore(TTrigger) direktifini kullanın:

phoneCall.Configure(State.Connected)
    .Ignore(Trigger.CallDialled);

Alternatif olarak, bir durum, yeniden girişli olarak işaretlenebilir, böylece giriş ve çıkış olayları, kendisinden / kendisinden geçerken bile tetiklenecektir:

stateMachine.Configure(State.Assigned)
    .PermitReentry(Trigger.Assigned)
    .OnEntry(() => SendEmailToAssignee());

Varsayılan olarak, tetikleyiciler açıkça göz ardı edilmelidir. İşlenmemiş bir tetikleyici tetiklendiğinde, Durumsuz'un varsayılan bir istisna fırlatma davranışını geçersiz kılmak için, OnUnhandledTrigger yöntemini kullanarak durum makinesini yapılandırın:

stateMachine.OnUnhandledTrigger((state, trigger) => { });


DOT grafiğine aktarma

Durum makinelerini çalışma zamanında görselleştirmek faydalı olabilir. Bu yaklaşımla, kod yetkili kaynak ve durum diyagramları her zaman güncel olan yan ürünlerdir.

phoneCall.Configure(State.OffHook)
    .PermitIf(Trigger.CallDialled, State.Ringing, IsValidNumber);
    
string graph = UmlDotGraph.Format(phoneCall.GetInfo());

UmlDotGraph.Format () metodu, DOT grafiği dilinde durum makinesinin dize temsilini döndürür, örn .:

digraph {
  OffHook -> Ringing [label="CallDialled [IsValidNumber]"];
}

PDF dosyası oluşturmak için komut satırı örneği: dot -T pdf -o phoneCall.pdf phoneCall.dot.


Asenkron Tetikleyiciler

Task<T>  sağlayan platformlarda, StateMachine, async giriş/çıkış eylemlerini ve benzerlerini destekler:

stateMachine.Configure(State.Assigned)
    .OnEntryAsync(async () => await SendEmailToAssignee());

Eşzamansız/Asenkron işleyiciler bu durumlarda * Async () metodları kullanılarak kaydedilmelidir.
Eşzamansız/Asenkron eylemleri tetikleyen bir tetikleyiciyi çalıştırmak için, FireAsync () meotdu kullanılmalıdır:

await stateMachine.FireAsync(Trigger.Assigned);

Not: StateMachine eşzamansız olarak kullanılabilirken, tek iş parçacıklı olarak kalır ve aynı anda birden çok iş parçacığı tarafından eşzamanlı kullanılamaz.


Yapı

Durumsuz, .NET 4.0 + 'da ve hemen hemen tüm modern .NET platformlarında .NET Standard 1.0'ı hedefleyerek çalışır. Visual Studio 2017, çözümü kurmak için gereklidir.


Proje hedefleri

Bu sayfa Durumsuz'un (Stateless) neredeyse tamamlanmış bir tanımlamasıdır ve açık amacı asgari düzeyde kalmaktır.

Hiç yorum yok:

Yorum Gönder

.net 6 mapget kullanımı

 app.UseEndpoints(endpoints => {     endpoints.MapGet("/", async context =>     {         var response = JsonConvert.Seriali...