Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

85
Visualizações
Cómo encapsular una máquina de estado sin estado .NET

Tengo un proyecto en el que hay un flujo de trabajo principalmente lineal. Estoy intentando usar la biblioteca .NET Stateless para actuar como motor de flujo de trabajo/máquina de estado. La cantidad de ejemplos disponibles es limitada, pero he compilado el siguiente código:

 private StateMachine<WorkflowStateType, WorkflowStateTrigger> stateMachine; private StateMachine<WorkflowStateType, WorkflowStateTrigger>.TriggerWithParameters<Guid, DateTime> registrationTrigger; private Patient patient; public Patient RegisterPatient(DateTime dateOfBirth) { configureStateMachine(WorkflowState.Unregistered); stateMachine.Fire<DateTime>(registrationTrigger, dateOfBirth); logger.Info("State changed to: " + stateMachine.State); return patient; } private void configureStateMachine(WorkflowState state) { stateMachine = new StateMachine<WorkflowState, WorkflowTrigger>(state); registrationTrigger = stateMachine.SetTriggerParameters<DateTime>(WorkflowTrigger.Register); stateMachine.Configure(WorkflowState.Unregistered) .Permit(WorkflowTrigger.Register, WorkflowStateType.Registered); stateMachine.Configure(WorkflowState.Registered) .Permit(WorkflowTrigger.ScheduleSampling, WorkflowState.SamplingScheduled) .OnEntryFrom(registrationTrigger, (dateOfBirth) => registerPatient(dateOfBirth)); } private void registerPatient(DateTime dateOfBirth) { //Registration code }

Como puede ver, estoy usando la sobrecarga Stateless Fire() que me permite pasar un disparador. Esto es para que pueda hacer que la máquina de estado procese la lógica comercial, en este caso, el código para registrar un nuevo paciente.

Todo esto funciona, pero ahora me gustaría mover todo el código de la máquina de estado a otra clase para encapsularlo y tengo problemas para hacerlo. Los desafíos que he tenido al hacer esto son:

  • instanciar un objeto StateMachine requiere que especifique el estado y State es una propiedad de solo lectura que solo se puede establecer en la instanciación.
  • mi disparador de registrationTrigger debe ser instanciado durante la configuración de la máquina de estado y también debe estar disponible para la clase que llama.

¿Cómo puedo superar estos elementos y encapsular el código de máquina de estado?

about 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Hay un artículo de Scott Hanselman con un ejemplo y una introducción a una biblioteca. También hay algunos ejemplos disponibles en su GitHub, incluido el ejemplo de implementación de errores mencionado en el artículo de Scott que encapsula la máquina de estado.

A continuación se muestra un ejemplo de cómo se puede extraer el estado del comportamiento:

 public class PatientRegistrationState { private StateMachine<WorkflowState, WorkflowTrigger> stateMachine; private StateMachine<WorkflowState, WorkflowStateTrigger>.TriggerWithParameters<DateTime> registrationTrigger; public PatientRegistrationState(State initialState = default(State)) { stateMachine = new StateMachine<WorkflowState, WorkflowTrigger>(initialState); stateMachine.Configure(WorkflowState.Unregistered) .Permit(WorkflowTrigger.Register, WorkflowStateType.Registered); stateMachine.Configure(WorkflowState.Registered) .Permit(WorkflowTrigger.ScheduleSampling, WorkflowState.SamplingScheduled) .OnEntryFrom(registrationTrigger, (date) => OnPatientRegistered(date)); } public WorkflowState State => stateMachine.State; public Action<DateTime> OnPatientRegistered {get; set;} = (date) => { }; // For state changes that do not require parameters. public void ChangeTo(WorkflowTrigger trigger) { stateMachine.Fire<DateTime>(trigger); } // For state changes that require parameters. public void ChangeToRegistered(DateTime dateOfBirth) { stateMachine.Fire<DateTime>(registrationTrigger, dateOfBirth); } // Change to other states that require parameters... } public class PatientRegistration { private PatientRegistrationState registrationState; private Patient patient; public PatientRegistration() { registrationState = PatientRegistrationState(WorkflowState.Unregistered) { OnPatientRegistered = RegisterPatient; } } public Patient RegisterPatient(DateTime dateOfBirth) { registrationState.ChangeToRegistered(dateOfBirth); logger.Info("State changed to: " + registrationState.State); return patient; } private void RegisterPatient(DateTime dateOfBirth) { // Registration code } }
about 4 years ago · Santiago Trujillo Relatório

0

Así lo logré en mi proyecto.

Lógica de flujo de trabajo separada para separar la clase. Tuve un par de flujos de trabajo basados en uno de los indicadores presentes en el objeto de solicitud; a continuación se muestra una de las clases de flujo de trabajo:

 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<SwiftRequestStatus, SwiftRequestTriggers>( () => 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); ..................... }

Que se activa desde el controlador/cualquier otra capa:

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

Como se mencionó anteriormente, tenía diferentes reglas de flujo de trabajo basadas en las condiciones del objeto de solicitud y, por lo tanto, usaba un patrón de fábrica WorkflowFactory.Get(request) ; puede crear una instancia de su flujo de trabajo/inyectarlo como desee

Y dentro de la clase de flujo de trabajo (clase BaseWorkflow en mi caso), he expuesto las acciones:

 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); }
about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda