ドットネットバージョン6で作成されたカスタムワークフロー、コンポーネント、マイクロサービス、およびその他の自動化ユーティリティ間のオークテーションを作成するために設計されたライブラリが設計されています
このライブラリは、あらゆる種類のプロセスのオーケストレーションに向けたエンティティのエコシステムを持つように設計されています。いくつかのクラス間の呼び出しなどの最も単純なプロセスから、マイクロサービスなどの呼び出しなどのより複雑なプロセスまで、常に宣言的な方法で、「if」、「else」などの退屈で複雑なネストの観点からコードを保存しようとしています。構造
このリポジトリでは、名前空間Magnett.automation.coreの下にグループ化されたこのエコシステムのコアクラスになります。これらのクラスの一部は、独立して有用になるほど十分なジェネリックであるため、ワークフローを作成する範囲外で使用できます。
この名前空間では、Librayクラス内で使用されているユーティリティクラスが見つかりました
コンセプトコンテキストは非常に一般的なものであり、いくつかの分野で使用されています。私たちにとって、コンテキストは、複数のコンポーネント間で共有されるように値が保存され、それらが不均一なタイプの値であるという共通の空間になります。
したがって、私たちはキー/バリューシステムの前にあり、値はあらゆるタイプになります。
コンテキストの構造は単純で、コンテキストクラスのみによって形成されます。コンテキストクラスは、値クラスの入力と取得、および値が保存されているボールトの定義となる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を生成するアクションコードを使用して別の状態に移行する可能性があります。
ある状態から別の状態に直接移動することはできません。そのため、特に1つの状態から行くことができるモデルがあります。
定義された遷移のない状態を与えることができ、これは状態が端子であることを意味します。このようにして、有限マシンまたは非フィニットマシンを定義できます。
ランタイム部分に関して、マシンの定義は、 MachinedefinitionBuilderクラスから生成されるImachinedefinitionインターフェイスから行われます。
マシン定義コードの例
//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インターフェイスがあります。このインターフェイスにより、将来的にサブフローを構築し、より複雑なアプリケーション内のサービスとしてカプセル化されたフローを作成することもできます。
基本的なフローで、フィールド値をリセットするための公正および初期ノード、次のノードが乱数にCacyulateするだけのノード、および両方の値を合計する最終ノードは、定義がそのようにソムシンである必要があります。
ワークフロー定義コードの例。
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 ( ) ;以前は、 ContextDefinitionなどのヘルパークラスを定義しており、コンテキストフィールドを含み、名前の定義を使用した複製を避けるための単なるクラスです。
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 ( ) ;
}
}また、すべてのノードクラスに基本クラスとして使用する抽象クラスの共通を作成しました。すべてのノードにAvalabaibain 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インターフェイスの下には、2つのノードタイプの同期と非同期があるため、両方のタイプのプロセスのラッパーとしてノードを使用できます。この例では、同期実装のみがあります。
この例では、同期ノードのみを使用します。
例ノード
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 ) ;
}
}インナークラスのexitcodesは、このノードのアバリブルエグジットコードの定義で列挙クラスを構築する別のヘルパークラスにすぎません。
ランナーは、それ自体をインスタンス化するために、ノード間で情報を共有するために使用されるワークフロー定義とコンテキストインスタンスを受信する必要があります。ランナーが実行されたら、ある場合はコンテキストから戻り値を取得できます。
抽象クラスの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 ( ) ;