設計用於創建自定義工作流程的庫,在Dotnet版本6上創建的組件,微服務和其他自動化實用程序之間的問題
該庫被設計為具有針對任何類型過程的編排的實體生態系統。從最簡單的過程(例如我們的幾個類之間的調用)到更複雜的過程,例如對微服務等的調用等。但是,始終以聲明性的方式,並希望根據“ if”,“ else”,“ else”等的繁瑣而復雜的嵌套來保存代碼。結構
在此存儲庫中,將是該生態系統的核心類別,分組為命名空間Magnett.Automation.core。這些類中的某些可以在創建工作流程的範圍之外使用,因為它們足夠通用,可以獨立使用。
在此名稱空間中,我們發現了圖書館類中使用的實用程序類
概念上下文是非常通用的東西,用於多個領域。對我們來說,上下文將是一個共同的空間,在該空間中存儲值以在幾個組件之間共享,因為它們是異質類型的值。
因此,我們在關鍵/值系統的前面,其中值是任何類型的。
上下文的結構很簡單,它僅由上下文類形成,這將是我們的價值類的輸入和檢索,而icontextVault接口將是存儲值的庫的定義。
默認情況下,我們將實現ICOntextVault的實現,它將將值存儲在內存中,但將開放任何其他以任何其他方式存儲這些值的實現。
我們將使用類上下文字段在上下文中獲取和設置值,而在此類中,我們可以定義類的類型和名稱。
如何在上下文中獲取 /設置值的示例
var context = Context . Create ( ) ;
var field = ContextField < int > . Create ( "FieldName" ) ;
//Set Value
context . Store ( field , random . Next ( 1000 ) ) ;
//Get Value
var value = context . Value ( field ) ; 我們可以使用幾個接口,以定義狀態機及其執行。機器的定義將與機器本身的執行分開,以避免耦合和清晰的職責分離。
主要接口是iMachine 。使用此接口,我們將使用當前狀態, ISTATE接口,以及使用生成過渡, Itransaction Entity的操作代碼過渡到另一個狀態的可能性。
只能通過過渡直接從一個狀態直接從一個狀態轉到另一種狀態,因此我們有一個模型,我們可以從一個州尤其來自一個狀態。
可以給出沒有定義過渡的狀態,這意味著狀態是終端。通過這種方式,我們可以定義有限或非有限機器。
關於運行時部件,將從Imachinedefinition接口完成機器的定義,該界面將從MachinedEfinitionBuilder類生成。
機器定義代碼的示例
//Helper class with states enumeration
public class State : Enumeration
{
public static readonly State Init = new State ( 1 , nameof ( Init ) ) ;
public static readonly State Working = new State ( 2 , nameof ( Working ) ) ;
public static readonly State Paused = new State ( 3 , nameof ( Paused ) ) ;
public static readonly State Finished = new State ( 4 , nameof ( Finished ) ) ;
private State ( int id , string name ) : base ( id , name )
{
}
}
//Helper class with action enumerations
public class Action : Enumeration
{
public static readonly Action Start = new Action ( 1 , nameof ( Start ) ) ;
public static readonly Action Pause = new Action ( 2 , nameof ( Pause ) ) ;
public static readonly Action Continue = new Action ( 3 , nameof ( Continue ) ) ;
public static readonly Action Finish = new Action ( 4 , nameof ( Finish ) ) ;
private Action ( int id , string name ) : base ( id , name )
{
}
}
//Now we can create a definition
_definition = MachineDefinitionBuilder . Create ( )
. InitialState ( State . Init )
. OnAction ( Action . Start ) . ToState ( State . Working )
. Build ( )
. AddState ( State . Working )
. OnAction ( Action . Pause ) . ToState ( State . Paused )
. OnAction ( Action . Finish ) . ToState ( State . Finished )
. Build ( )
. AddState ( State . Paused )
. OnAction ( Action . Continue ) . ToState ( State . Working )
. Build ( )
. AddState ( State . Finished )
. Build ( )
. BuildDefinition ( ) ;機器創建和使用代碼的示例。
var machine = Machine
. Create ( SimpleMachineDefinition . GetDefinition ( ) ) ;
machine . Dispatch ( Action . Start ) ;
var currentState = machine . State ; 在此名稱空間下,我們將有必要的類來定義工作流並執行它。與上一節一樣,我們將使工作流定義與執行分開。
將使用IWorkFlowDefinition和IWorkFlowRunner接口進行此分離。
為了封裝定義和執行,我們具有IFLOW接口,此接口還將允許我們將來構建子花,創建在更複雜的應用程序中封裝為服務的流量...等。
如果我們在基本流中考慮重置字段值的公正和初始節點,則下一個節點只是為了陷入隨機數,並且最終的節點要匯總兩個值,這兩個值應該是這樣的。
示例工作流定義代碼。
var contextDefinition = ContextDefinition . Create ( ) ;
var definition = FlowDefinitionBuilder . Create ( )
. WithInitialNode ( ResetValue . Create ( Node . Reset , contextDefinition ) )
. OnExitCode ( ResetValue . ExitCode . Ok ) . GoTo ( Node . SetValue )
. Build ( )
. WithNode ( SetValue . Create ( Node . SetValue , contextDefinition ) )
. OnExitCode ( SetValue . ExitCode . Assigned ) . GoTo ( Node . SumValue )
. Build ( )
. WithNode ( SumValue . Create ( Node . SumValue , contextDefinition ) ) . Build ( )
. BuildDefinition ( ) ;以前,您已經定義了一些輔助類,例如上下文定義,這只是一個包含上下文字段的類,並避免使用名稱定義重複。
internal class ContextDefinition
{
public ContextField < int > FirstDigit { get ; }
public ContextField < int > SecondDigit { get ; }
public ContextField < int > Result { get ; }
private ContextDefinition ( )
{
FirstDigit = ContextField < int > . Create ( "FieldOne" ) ;
SecondDigit = ContextField < int > . Create ( "FieldTwo" ) ;
Result = ContextField < int > . Create ( "FieldResult" ) ;
}
public static ContextDefinition Create ( )
{
return new ContextDefinition ( ) ;
}
}我們還創建了我們將用作所有節點類的基類的抽像類常見,我們將以一種方法來確保所有節點都具有可用的conxtextDefinition
internal abstract class Common : Core . WorkFlows . Implementations . Node
{
protected ContextDefinition ContextDefinition { get ; }
protected Common ( CommonNamedKey key , ContextDefinition contextDefinition ) : base ( key )
{
ContextDefinition = contextDefinition
?? throw new ArgumentNullException ( nameof ( contextDefinition ) ) ;
}
}在Inode和Inodeasync接口下,我們有兩種節點類型同步和異步,因此我們可以將節點用作兩種類型過程的包裝器。在此示例中,我們只有同步實現。
在我們的示例中,我們將僅使用同步節點。
示例節點
internal class ResetValue : Common
{
#region ExitCodes
public class ExitCode : Enumeration
{
public static readonly ExitCode Ok = new ExitCode ( 1 , "Ok" ) ;
private ExitCode ( int id , string name ) : base ( id , name )
{
}
}
#endregion
private ResetValue ( CommonNamedKey key , ContextDefinition contextDefinition ) :
base ( key , contextDefinition )
{
}
public override NodeExit Execute ( Context context )
{
context . Store ( ContextDefinition . FirstDigit , 0 ) ;
context . Store ( ContextDefinition . SecondDigit , 0 ) ;
context . Store ( ContextDefinition . Result , 0 ) ;
return NodeExit . Create ( ExitCode . Ok . Name ) ;
}
public static ResetValue Create ( CommonNamedKey name , ContextDefinition contextDefinition )
{
return new ResetValue ( name , contextDefinition ) ;
}
}內部類別的出口碼只是另一個輔助類別,在枚舉類中構建具有此節點可用出口代碼的定義,我們還使用somthin similira
為了實例化,跑步者將需要接收工作流定義和上下文實例,該實例將用於共享節點之間的信息。執行跑步者後,如果有的話,我們可以從上下文中檢索返回值。
我們擁有抽像類FlowRunnerBase,因此我們可以實現我們的自定義跑步者,步驟逐步,分佈式等。
示例流跑者
var flowRunner = FlowRunner . Create ( definition , Context . Create ( ) ) ;
var exit = await flowRunner . Start ( ) ;正如我們之前所說的,這是所有這些過程的包裝器,現在具有基本功能,但是將來版本將用作工作流管理的主要類。
var definition = SimpleFlowDefinition . GetDefinition ( ) ;
var context = Context . Create ( ) ;
var flow = Flow . Create ( FlowRunner . Create ( definition , context ) ) ;
var exit = await flow . Run ( ) ;