Programmatic schema builder
This functionality is available in Workflow Engine 13.3.0 and later.
With the Workflow Engine Builder, you can create workflow schemas programmatically without using a designer interface. To work with the
Builder, you need to initialize
the IProcessDefinitionBuilder
interface:
IProcessDefinitionBuilder processDefinitionBuilder = ProcessDefinitionBuilder.Create("SchemeName");
IProcessDefinitionBuilder
provides the necessary methods for creating workflow elements. After creating elements, you can set additional
options. For example, to create a new activity, you can call
the CreateActivity
method with a name, then set the state
, mark it as
initial
, and position it on the schema using coordinates.
processDefinitionBuilder
.CreateActivity("InitialActivity")
.State("Initial")
.Initial()
.EnableSetState()
.EnableAutoSchemeUpdate()
.SetX(320).SetY(220)
.Ref(out ActivityDefinition activity1)
.CreateActivity("FinalActivity")
.State("Final")
.Final()
.EnableSetState()
.EnableAutoSchemeUpdate()
.SetX(520).SetY(220)
.Ref(out ActivityDefinition activity2);
The Ref
method
allows you to obtain a reference to the created definition for further use.
Similarly, you can create commands and transitions using
the CreateCommand
and CreateTransition
methods, respectively.
processDefinitionBuilder
.CreateCommand("Go")
.Ref(out CommandDefinition goCommand)
.CreateTransition("TransitionName", activity1, activity2)
.Direct();
For a complete list of methods, refer to the API Reference. Below you can see an example of creating a complete schema.
var builder = ProcessDefinitionBuilder.Create("SimpleWF");
// Implement actors
builder.CreateActor("Approver", "CheckRole")
.Value("Approver")
.Ref(out ActorDefinition actorApprover);
// Implement process parameters
builder.CreateParameter("Parameter", typeof(string), ParameterPurpose.Persistence)
.Ref(out ParameterDefinition processParameter);
// Implement Code
builder.CreateCodeCondition("CheckStartParameter")
.Code($"string startParameter = processInstance.GetParameter<string>(\"{processParameter.Name}\");\n" +
$"if (startParameter == \"reject\")\n" +
$"{{\n" +
$"\treturn true;\n" +
$"}}\n\n" +
$"return false;");
builder.CreateCodeAction("LogAction")
.Code("Console.WriteLine($\"The parameter with value = {parameter} has been approved!\");");
// Implement activities
builder.CreateActivity("Initial")
.Initial()
.State("Initial")
.EnableSetState()
.SetX(320).SetY(220)
.Ref(out ActivityDefinition initialActivity);
builder.CreateActivity("Activity")
.State("Activity")
.SetX(620).SetY(220)
.Ref(out ActivityDefinition activity);
builder.CreateActivity("FinalActivity")
.Final()
.State("Final")
.SetX(920).SetY(220)
.CreateImplementationAtBegin("LogAction").ActionParameter($"@{processParameter.Name}")
.Ref(out ActivityDefinition finalActivity);
// Implement commands
builder.CreateCommand("StartCommand")
.CreateCommandParameter("StartParameter", processParameter).Required()
.Ref(out CommandDefinition startCommand);
// Implement timers
builder.CreateTimer("TimeOut")
.Interval(TimeSpan.FromSeconds(30))
.Ref(out TimerDefinition timeoutTimer);
builder.CreateCommand("ApproveCommand")
.Ref(out CommandDefinition approveCommand);
// Implement transitions
builder.CreateTransition("initialActivity_to_activity", initialActivity, activity)
.TriggeredByCommand(startCommand)
.Direct();
builder.CreateTransition("activity_to_finalActivity", activity, finalActivity)
.TriggeredByCommand(approveCommand)
.CreateRestriction(actorApprover, RestrictionType.Allow)
.Direct();
builder.CreateTransition("activity_to_initialActivity", activity, initialActivity)
.TriggeredByTimer(timeoutTimer)
.SetX(540).SetY(350)
.Reverse();
builder.CreateTransition("acivity_to_initialActivity_reject", activity, initialActivity)
.Auto()
.Conditional().CreateCondition("CheckStartParameter")
.SetX(545).SetY(150)
.Reverse();
As a result, the following scheme will be created: