2012-11-12 30 views
8

bbv.Common.StateMachine lớp là mã máy trạng thái tốt nhất mà tôi từng thấy. Nhưng nó thiếu một điều: nhận trạng thái hiện tại.Cách nhận trạng thái hiện tại từ lớp bbv.Common.StateMachine (hiện tại là Appccelerate.StateMachine)?

Đây là một hệ thống theo dõi thứ tự:

fsm = new ActiveStateMachine<States, Events>(); 

     fsm.In(States.OrderCreated) 
      .On(Events.Submitted) 
      .Goto(States.WaitingForApproval); 
     fsm.In(States.WaitingForApproval) 
      .On(Events.Reject) 
      .Goto(States.Rejected); 
     fsm.In(States.WaitingForApproval) 
      .On(Events.Approve) 
      .Goto(States.BeingProcessed); 
     fsm.In(States.BeingProcessed) 
      .On(Events.ProcessFinished) 
      .Goto(States.SentByMail); 
     fsm.In(States.SentByMail) 
      .On(Events.Deliver) 
      .Goto(States.Delivered); 

     fsm.Initialize(States.OrderCreated); 
     fsm.Start(); 
     fsm.Fire(Events.Submitted); 
     // Save this state to database 

Bạn có thể xem làm thế nào nó hoạt động một cách dễ dàng.

Nhưng tôi muốn lưu trạng thái đơn đặt hàng trong cơ sở dữ liệu. Vì vậy, tôi sẽ có thể hiển thị trong đó nhà nước là thứ tự.

Tôi cần một phương pháp

fsm.GetCurrentState() 
//show this state in the a table 

. Trên thực tế có một cách: Tôi có thể sử dụng ExecuteOnEntry và thay đổi giá trị cục bộ trên mỗi mục nhập của tiểu bang. Nhưng nó sẽ là cồng kềnh để viết ExecuteOnEntry cho mọi tiểu bang bởi vì tôi sẽ lặp lại bản thân mình!

Phải có cách tinh tế để thực hiện.

+1

Did bạn biết rằng bbv.Common đã được đổi tên thành Appccelerate. Hãy xem trang chủ mới của chúng tôi http://www.appccelerate.com –

Trả lời

13

Như Daniel giải thích, điều này là do thiết kế. Hãy để tôi giải thích lý do:

Máy trạng thái cho phép xếp hàng các sự kiện. Do đó, yêu cầu máy trạng thái về trạng thái hiện tại của nó có thể gây hiểu nhầm. Nó hiện đang ở trạng thái A, nhưng đã có một sự kiện được xếp hàng chờ đến trạng thái B.

Hơn nữa, tôi coi đó là thiết kế tồi, để kết nối trạng thái nội bộ của máy trạng thái định nghĩa máy trạng thái) trực tiếp với các trạng thái bên ngoài của máy trạng thái (các trạng thái bạn muốn tồn tại trong cơ sở dữ liệu). Nếu bạn ghép nối hai trực tiếp này, bạn sẽ mất khả năng cấu trúc lại máy trạng thái bên trong mà không ảnh hưởng đến bên ngoài (trong trường hợp của bạn là cơ sở dữ liệu). Tôi thường xuyên gặp phải tình huống trong đó tôi phải chia một tiểu bang A, thành A1 và A2 bởi vì tôi phải đính kèm các hành động khác nhau cho họ, nhưng dù sao họ vẫn đại diện cho cùng một trạng thái với môi trường. Vì vậy, tôi khuyên bạn nên tách biệt các trạng thái bên trong và bên ngoài, hoặc khi bạn đã viết bằng OnEntryExecute() hoặc bằng cách cung cấp ánh xạ và sử dụng phần mở rộng. Đây là một phần mở rộng đó sẽ giúp bạn có được tình trạng hiện tại:

public class CurrentStateExtension : ExtensionBase<State, Event> 
{ 
    public State CurrentState { get; private set; } 

    public override void SwitchedState(
     IStateMachineInformation<State, Event> stateMachine, 
     IState<State, Event> oldState, 
     IState<State, Event> newState) 
    { 
     this.CurrentState = newState.Id; 
    } 
} 

Bạn có thể thêm phần mở rộng vào máy nhà nước theo cách này:

currentStateExtension = new CurrentStateExtension(); 
machine.AddExtension(currentStateExtension); 

Tất nhiên bạn có thể sử dụng phần mở rộng này trực tiếp để có được quyền truy cập với trạng thái hiện tại. Để làm cho nó trở nên đơn giản hơn, hãy để lớp định nghĩa máy trạng thái thực hiện phần mở rộng và tự chuyển nó thành một phần mở rộng.Hãy để bạn thoát khỏi lớp học thêm.

Một lưu ý cuối cùng: khi bạn đặt câu hỏi về bbv.Common (hoặc Appccelerate như nó được gọi bây giờ) trong nhóm google tại https://groups.google.com/forum/?fromgroups#!forum/appccelerate, thật dễ dàng cho tôi để tìm thấy những câu hỏi và trả lời nó ;-)

+0

Cảm ơn, tôi sẽ thử ASAP. –

4

Đây là theo thiết kế. Chúng tôi xem xét truy vấn trạng thái của máy trạng thái như mùi thiết kế. Nhưng tất nhiên có trường hợp ngoại lệ. Bạn có hai tùy chọn sau:

  1. Sử dụng các phương pháp ExecuteOnEntry để lưu trạng thái của đơn đặt hàng. Điều này phản ánh con đường để đi bởi vì bạn không wan't để rò rỉ các tiểu bang của statemachine vào logic kinh doanh của bạn.
  2. Viết trình trang trí máy trạng thái của riêng bạn sử dụng nội bộ StateMachine<TState, TEvent>. Điều này cho thấy trạng thái.

Daniel