Skip to main content

Introducing Formengine - The New Formbuilder, try for FREE formengine.io.

Programmatic schema builder

info

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:

Scheme1