2009-08-06 29 views
13

Mã này trông giống như dưới đây:khi một sự kiện có nhiều người đăng ký, làm cách nào để tôi nhận được giá trị trả lại cho từng người đăng ký?

Đồng hồ:

public class Clock 
{ 
    public event Func<DateTime, bool> SecondChange; 

    public void Run() 
    { 
     for (var i = 0; i < 20; i++) 
     { 
      Thread.Sleep(1000); 

      if (SecondChange != null) 
      { 
       //how do I get return value for each subscriber? 
       Console.WriteLine(SecondChange(DateTime.Now)); 
      } 
     } 
    } 
} 

DisplayClock:

public class DisplayClock 
{ 
    public static bool TimeHasChanged(DateTime now) 
    { 
     Console.WriteLine(now.ToShortTimeString() + " Display"); 
     return true; 
    } 
} 

LogClock:

public class LogClock 
{ 
    public static bool WriteLogEntry(DateTime now) 
    { 
     Console.WriteLine(now.ToShortTimeString() + " Log"); 
     return false; 
    } 
} 

Để chạy mã:

var theClock = new Clock(); 
theClock.SecondChange += DisplayClock.TimeHasChanged; 
theClock.SecondChange += LogClock.WriteLogEntry; 
theClock.Run(); 

Các câu hỏi khác là:

  • Có thực hành tốt cho mỗi thuê bao để trả về một giá trị?
  • Thực tiễn tốt là chỉ cần khai báo Hành động/Func làm loại trả về sự kiện thay vì khai báo thủ công một đại biểu?

Trả lời

26

Sử dụng Delegate.GetInvocationList.

if (SecondChange != null) 
{ 
    DateTime now = DateTime.Now; 
    foreach (Delegate d in SecondChange.GetInvocationList()) 
    { 
     Console.WriteLine(d.DynamicInvoke(now)); 
    } 
} 

là nó thực hành tốt để chỉ cần sử dụng Action/Func thay vì bằng tay tuyên bố một đại biểu?

Có. Nhưng tôi sẽ chỉ ra rằng thực hành tốt nhất là cho các sự kiện để sử dụng EventHandler<T> thay vì Func<..., TResult>. EventHandler<T> không hỗ trợ các giá trị trả lại, nhưng bạn có phần hợp lý trong đó có một vài sự kiện .NET có giá trị trả lại. Tôi sẽ xem xét tốt hơn là có thuộc tính có thể đặt trước trong lớp con tùy chỉnh EventArgs mà bạn sử dụng làm T. Đây là mẫu mà chúng ta thấy trong những thứ như KeyEventArgs.Handled. Bằng cách này, bạn có thể sử dụng EventHandler<T> và người đăng ký cũng có thể điều phối phản hồi của họ ở mức giới hạn bằng cách nhận và đặt thuộc tính này.

+0

Thank you very much. – Jeff

+1

Không đồng ý. Các (đối tượng người gửi, EventArgs e) mô hình có đầy đủ các tinh tế tốt đẹp. Xem cả hai câu trả lời được chấp nhận tại đây: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/83e9f2f4-908b-4679-811d-c5b1471730d7 –

+0

Ok, tôi thấy quan điểm của bạn. – Jeff

0

Tôi nghĩ hoàn toàn tốt khi sử dụng Hành động/Func thay vì người được ủy quyền.

NHƯNG Sự kiện không được cho là được sử dụng như vậy. Chúng được kích hoạt tại thời điểm không xác định, vì vậy bạn không biết tất cả các tham số.

gì bạn thực sự cần phải có lẽ là:

  1. Sử dụng đa hình cho đồng hồ.
  2. Sử dụng mẫu khách truy cập/người đăng ký/người quan sát để nhận giá trị của họ.

Vì vậy, các mã sẽ trông giống như:

var theClock = new Clock(); 
theClock.AddSecondsSubscriber(new DisplayClock()); 
theClock.AddSecondsSubscriber(new LogClock()); 
theClock.RunAndExecuteVisitors(theBoolResultYouNeed => Console.WriteLine(theBoolResultYouNeed)); 
Các vấn đề liên quan