2010-04-19 29 views
6

lớp của tôi với một sự kiện:sự kiện hội nghị - Tôi không nhận được nó

public class WindowModel 
{ 
    public delegate void WindowChangedHandler(object source, WindowTypeEventArgs e); 
    public event WindowChangedHandler WindowChanged; 

    public void GotoWindow(WindowType windowType) 
    { 
     this.currentWindow = windowType; 
     this.WindowChanged.Invoke(this, new WindowTypeEventArgs(windowType)); 
    } 
} 

nguồn gốc lớp sự kiện:

public class WindowTypeEventArgs : EventArgs 
{ 
    public readonly WindowType windowType; 

    public WindowTypeEventArgs(WindowType windowType) 
    { 
     this.windowType = windowType; 
    } 
} 

Một số lớp khác mà đăng ký nó tới sự kiện:

private void SetupEvents() 
{ 
    this.WindowModel.WindowChanged += this.ChangeWindow; 
} 

private void ChangeWindow(object sender, WindowTypeEventArgs e) 
{ 
    //change window 
} 

Tôi đã đạt được gì sau khi thực hiện theo quy ước .Net? Nó sẽ có ý nghĩa hơn để có một hợp đồng như thế này

public delegate void WindowChangedHandler(WindowType windowType); 
public event WindowChangedHandler WindowChanged; 

Làm theo cách này, tôi không cần phải tạo ra một lớp mới và là dễ hiểu hơn. Tôi không mã hóa thư viện .Net. Mã này sẽ chỉ được sử dụng trong dự án này. Tôi thích các công ước nhưng tôi có đúng không khi tôi nói rằng trong ví dụ này, nó không có ý nghĩa hoặc tôi đã hiểu nhầm điều gì đó?

Trả lời

15

xem trong sự cô lập, vâng, bạn đúng: cú pháp thông thường NET là tiết hơn và ít trực quan, nhưng có ưu điểm:

  • sửa đổi đối với các thông tin thông qua sự kiện của bạn không tự động yêu cầu thay đổi đối với mọi người tiêu dùng của sự kiện. Ví dụ: nếu bạn muốn thêm một phần thông tin bổ sung vào sự kiện của mình - giả sử, một chuỗi WindowTitle - bạn sẽ phải sửa đổi chữ ký của mọi hàm duy nhất được gắn với sự kiện đó, bất kể chúng có hay không sử dụng nó. Với cách tiếp cận EventArgs, bạn thêm thuộc tính vào đối số và chỉ thay đổi các chức năng cần tận dụng lợi thế cho thông tin bổ sung.
  • Vì .NET 2.0 đã giới thiệu loại EventHandler<TEventArgs> ủy nhiệm, bạn không còn cần xác định các đại biểu sự kiện của mình theo cách thủ công nữa. Trong ví dụ của bạn, bạn sẽ nhập sự kiện của mình là EventHandler<WindowTypeEventArgs> thay vì WindowChangedHandler.
  • Cách tiếp cận EventArgs giúp dễ dàng chuyển nhiều loại thông tin trở lại chức năng gọi. Nếu bạn cần thực hiện điều này trong ví dụ thay thế của bạn (ví dụ chuyển trực tiếp tham số sự kiện), bạn vẫn sẽ tạo ra lớp -uple của riêng bạn để giữ thông tin.

Tác động của ảnh đầu tiên được thể hiện rõ hơn khi bạn xem mẫu thực tế cho.NET sự kiện trong việc tạo ra một chức năng protected virtual mà thực sự không gọi. Ví dụ:

public event EventHandler<WindowTypeEventArgs> WindowChanged; 

protected virtual void OnWindowChanged(WindowTypeEventArgs e) 
{ 
    var evt = WindowChanged; 

    if(evt != null) evt(this, e); 
} 

Có một vài điều tôi muốn chỉ ra ở đây:

  1. Sử dụng mô hình của việc tạo ra phương pháp event-cách gọi này cho phép bạn để tránh kiểm tra rỗng suốt mã của bạn (một sự kiện không có bất kỳ chức năng nào gắn liền với nó sẽ là null và sẽ ném một ngoại lệ nếu bạn cố gắng gọi nó)
  2. Mẫu này cũng cho phép các lớp kế thừa từ bạn kiểm soát thứ tự gọi, cho phép chúng thực thi mã của chúng một cách rõ ràng trước hoặc sau bất kỳ người tiêu dùng bên ngoài nào
  3. Điều này đặc biệt quan trọng trong môi trường đa luồng. Nếu bạn chỉ nói if(WindowChanged != null) WindowChanged(this, e);, bạn thực sự sẽ có nguy cơ xảy ra sự kiện WindowChanged trở thành null giữa thời gian bạn kiểm tra và thời gian bạn gọi. Điều này không quan trọng trong các tình huống đơn luồng, nhưng là một thói quen phòng thủ tuyệt vời để hình thành.
+0

Tôi thực sự thích câu trả lời này! Điểm đầu tiên là rất rõ ràng, nhưng một cái gì đó tôi đã không nghĩ về. Điểm thứ hai tôi không biết nhưng nó là rất tốt đẹp :) Không chắc tôi hiểu điểm thứ ba của bạn. Cảm ơn! –

+0

@bobjink: Rất vui được! Điểm thứ ba của tôi là về việc có thể gửi dữ liệu trở lại đối tượng đang gọi sự kiện. Sử dụng cách tiếp cận 'EventArgs', bạn có thể cho phép người tiêu dùng của sự kiện của bạn sửa đổi một thuộc tính trên nó, giống như trên lớp' CancelEventArgs', nó sẽ cho phép nó truyền dữ liệu cho bạn. –

+0

Tôi thấy ngay bây giờ! Cảm ơn :) –

1

Bạn có thể sử dụng đại biểu của mình. Không ai sẽ ép buộc bạn. Nó chỉ là một mô hình tốt cho các sự kiện.

Nếu bạn sử dụng standart Sender-EventArgs, bạn sẽ có thể sử dụng cùng một trình xử lý ChangeWindow cho các sự kiện khác.

3

Tôi nhận ra sự nhầm lẫn của bạn! Tôi cũng có cảm giác tương tự khi lần đầu tiên tôi nhìn vào điều này.

Điều quan trọng cần nhận ra là nó không mang lại cho bạn nhiều lợi thế về mặt lập trình, nhưng nó là một quy ước được biết đến trong khuôn khổ. Như vậy, có rất nhiều công cụ mong đợi chữ ký void EventName(object sender, EventArgs e). Ví dụ, một số vùng chứa IoC có thể sử dụng chữ ký này cho các sự kiện dây tự động vào thời gian xây dựng.

Tóm lại, có vẻ hơi lạ, nhưng đó là một quy ước. Gắn bó với nó và bóng đèn sẽ sáng lên cuối cùng!

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