How to encapsulate .NET Stateless state machine

前端 未结 2 876
小蘑菇
小蘑菇 2021-02-14 02:50

I have a project where there is a mostly linear workflow. I\'m attempting to use the .NET Stateless library to act as workflow engine/state machine. The number of examples out

2条回答
  •  故里飘歌
    2021-02-14 02:59

    This is how I achieved it in my project.

    Separated workflow logic to separate class. I had couple of workflows based on one of the flags present in the request object; below is one of the workflow classes:

    public class NationalWorkflow : BaseWorkflow
    {
        public NationalWorkflow(SwiftRequest request) : this(request, Objects.RBDb)
        { }
    
        public NationalWorkflow(SwiftRequest request, RBDbContext dbContext)
        {
            this.request = request;
            this.dbContext = dbContext;
            this.ConfigureWorkflow();
        }
    
        protected override void ConfigureWorkflow()
        {
            workflow = new StateMachine(
               () => request.SwiftRequestStatus, state => request.SwiftRequestStatus = state);
    
            workflow.OnTransitioned(Transitioned);
    
            workflow.Configure(SwiftRequestStatus.New)
                .OnEntry(NotifyRequestCreation)
                .Permit(SwiftRequestTriggers.ProcessRequest, SwiftRequestStatus.InProgress);
    
            workflow.Configure(SwiftRequestStatus.InProgress)
                .OnEntry(ValidateRequestEligibility)
                .Permit(SwiftRequestTriggers.AutoApprove, SwiftRequestStatus.Approved)
                .Permit(SwiftRequestTriggers.AdvancedServicesReview, SwiftRequestStatus.PendingAdvancedServices);
    
    .....................
    }
    

    Which is triggered from the controller/any other layer:

    private static void UpdateRequest(SwiftRequestDTO dtoRequest)
        {
                var workflow = WorkflowFactory.Get(request);
                workflow.UpdateRequest();
        }
    

    As mentioned above, I had different workflow rules based on conditions in the request object and hence used a factory pattern WorkflowFactory.Get(request); you may create an instance of your workflow/inject it as desired

    And inside the workflow class (BaseWorkflow class in my case), I have exposed the actions:

        public void UpdateRequest()
        {
            using (var trans = this.dbContext.Database.BeginTransaction())
            {
                this.actionComments = "Updating the request";
                this.TryFire(SwiftRequestTriggers.Update);
    
                SaveChanges();
                trans.Commit();
            }
        }
    
      protected void TryFire(SwiftRequestTriggers trigger)
        {
            if (!workflow.CanFire(trigger))
            {
                throw new Exception("Cannot fire " + trigger.ToString() + " from state- " + workflow.State);
            }
            workflow.Fire(trigger);
        }
    

提交回复
热议问题