2013-05-21 26 views
6

Có sẵn sàng sử dụng giải pháp nào cho các sự kiện nhóm không?sự kiện nhóm trong C#

Giả sử tôi có hai sự kiện: A và B. Tôi muốn Phương thức M được thực thi khi A và B đã được kích hoạt, chúng không cần phải bắn chính xác cùng một lúc.

Giống như: Sự kiện nhóm G kích hoạt sau khi cả hai, A và B đã kích hoạt. Tôi chỉ cần đăng ký Phương thức M tại sự kiện Nhóm G.

Có thể bắn nhiều lần, G sẽ chỉ kích hoạt sau khi B đã kích hoạt. Cùng một cách khác.

Tôi đang tìm thư viện có các sự kiện này.

Chỉnh sửa: Ví dụ

Events: 
    A | B | G 
1 F 0 0 
2 0 F F 
3 0 F 0 
4 0 F 0 
5 0 F 0 
6 F 0 F 
7 F 0 0 
8 0 F F 
9 0 0 0 
10 F F F 

F nghĩa sự kiện cháy, nó không.

+4

Không biết về bất cứ điều gì như thế, nhưng nếu bạn nói a, a, a, b, b bị sa thải, bao nhiêu lần g sẽ được kích hoạt trong trường hợp này? – vittore

+0

Hoặc bạn có đảm bảo trong mã của mình rằng A và B chỉ kích hoạt một lần cho một phiên bản cụ thể không? Thêm chi tiết sẽ thực sự giúp đỡ. – Renan

Trả lời

7

Bạn có thể sử dụng Reactive Extensions.

Nhìn vào phương thức Observable.FromEvent (hoặc Observable.FromEventPattern) để chuyển đổi sự kiện .NET chuẩn thành có thể quan sát và sau đó bạn có thể nhóm các kết quả bằng cách sử dụng Observable.CombineLatest.

Đây là một mã giả:

var observableA = Observable.FromEvent(yourEventA); 
var observableB = Observable.FromEvent(yourEventB); 

var observableG = observableA.CombineLatest(observableB, ...) 

Các tạo ra quan sát được kích hoạt khi cả hai sự kiện được kích hoạt.

EDIT

CombineLatest tạo ra một đầu ra với kết quả mới nhất, mà không cần thiết lập lại trạng thái của nó. Vì vậy, ví dụ nếu A1 được bắn sau đó B1 được bắn G1 được sản xuất với (A1 + B1), nhưng nếu B2 được bắn thì G2 được sản xuất với (A1 + B2) và ...

Để sản xuất chính xác kết quả mong đợi bạn có thể viết một cái gì đó như:

private void SetupEvents() 
    { 
     var observableA = Observable.FromEventPattern((e) => btA.Click += e, (e) => btA.Click -= e); 
     var observableB = Observable.FromEventPattern((e) => btB.Click += e, (e) => btB.Click -= e); 

     EventPattern<object> lastA = null; 
     EventPattern<object> lastB = null; 
     var observableG = observableA.CombineLatest(observableB, (rA, rB) => 
     { 
      if (lastA == rA || lastB == rB) 
       return null; 

      lastA = rA; 
      lastB = rB; 
      return new Tuple<EventPattern<object>, EventPattern<object>>(rA, rB); 
     }).Where(p => p != null); 

     observableG.Subscribe(r => Trace.WriteLine("A + B")); 

     // or use ToEvent to generate another standard .NET event 
     //observableG.ToEvent().OnNext += GEvent; 
    } 

    //void GEvent(System.Reactive.EventPattern<object> obj) 
    //{ 
    // Trace.WriteLine("A + B"); 
    //} 

Về cơ bản tôi kiểm tra xem kết quả mới nhất có khác với kết quả hiện tại hay không. Có thể có một số phần mở rộng RX gốc cho trường hợp của bạn nhưng tôi không thể tìm thấy nó.

3

Tôi nghĩ rằng Reactive Extensions có lẽ là gần nhất với những gì bạn đang tìm kiếm. Nó cung cấp các trình trợ giúp để biến các sự kiện thành các quan sát và một cú pháp kiểu LINQ mà bạn có thể sử dụng để soạn các quan sát đó.

0

Bạn có thể tự mình viết một lớp như vậy. Dưới đây là một (rất) thực hiện tầm thường:

 
public class TwoEventGroup 
{ 
    private bool _eventAFired; 
    private bool _eventBFired; 

    public void EventAHandler() 
    { 
     _eventAFired = true; 
     TestAndFire(); 
    } 

    public void EventBHandler() 
    { 
     _eventBFired = true; 
     TestAndFire(); 
    } 

    private void TestAndFire() 
    { 
     if (_eventAFired && _eventBFired) 
     { 
     _eventAFired = false; 
     _eventBFired = false; 
     if (GroupEvent != null) 
      GroupEvent(); 
     } 
    } 

    public event Action GroupEvent; 
} 

Đây chỉ là một việc thực hiện khái niệm, bạn có thể muốn có các đại biểu sự kiện như một chung, mở rộng nó với các sự kiện n thay vì chỉ hai, (có thể) thỏa thuận với thời gian chờ giữa quá trình kích hoạt sự kiện, hãy nghĩ về cách lớp này sẽ được gia hạn (nếu có), v.v.

@spender gợi ý của Rx đáng giá (+1) nhưng thư viện hướng đến các sự kiện không đồng bộ và có phần đường cong học tập dốc.Nó có thể là overkill nếu bạn chỉ muốn nhóm đơn giản của các sự kiện được biết đến, hoặc các sự kiện cùng loại và không phải là một cái gì đó hoàn toàn chung chung.

Các vấn đề liên quan