intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Cơ chế ủy quyền và sự kiện phần cuối

Chia sẻ: Tuan Bui Nghia | Ngày: | Loại File: PDF | Số trang:15

99
lượt xem
11
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Phương thức Run tạo vòng lặp vô hạn để kiểm tra định kỳ thời gian hệ thống. Nếu thời gian thay đổi từ đối tượng Clock hiện hành, thì nó sẽ cảnh báo cho tất cả các subscriber và sau đó cập nhật lại những trạng thái của nó.

Chủ đề:
Lưu

Nội dung Text: Cơ chế ủy quyền và sự kiện phần cuối

  1. public void Run() { for(;;) { // ngừng 10 giây Thread.Sleep( 10 );
  2. // lấy thời gian hiện hành System.DateTime dt = System.DateTime.Now; // nếu giây thay đổi cảnh báo cho subscriber if ( dt.Second != second) { // tạo TimeInfoEventArgs để truyền // cho subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); // nếu có bất cứ lớp nào đăng ký thì cảnh báo if ( OnSecondChange != null) { OnSecondChange( this, timeInformation); } } // cập nhật trạng thái this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } } Phương thức Run tạo vòng lặp vô hạn để kiểm tra định kỳ thời gian hệ thống. Nếu thời gian thay đổi từ đối tượng Clock hiện hành, thì nó sẽ cảnh báo cho tất cả các subscriber và sau đó cập nhật lại những trạng thái của nó. Bước đầu tiên là ngừng 10 giây: Thread.Sleep(10); Ở đây chúng ta sử dụng phương thức tĩnh của lớp Thread từ System.Threading của .NET. Sử dụng phương thức Sleep() để kéo dài khoảng cách giữa hai lần thực hiện vòng lặp. Sau khi ngừng 10 mili giây, phương thức sẽ kiểm tra thời gian hiện hành: System.DateTime dt = System.DateTime.Now; Cứ khoảng 100 lần kiểm tra, thì một giây sẽ được gia tăng. Phương thức ghi nhận sự thay đổi và cảnh báo đến những subscriber của nó. Để làm được điều này, đầu tiên phải tạo ra một đối tượng TimeInfoEventArgs: if ( dt.Second != second) {
  3. // tạo TimeInfoEventArgs để truyền cho các subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); } Và để cảnh báo cho những subscriber bằng cách kích hoạt sự kiện OnSecondChange: // cảnh báo cho các subscriber if ( OnSecondChange != null) { OnSecondChange( this, timeInformation); } Nếu một sự kiện không có bất cứ lớp subscriber nào đăng ký thì nó ước lượng giá trị là null. Phần kiểm tra bên trên xác định giá trị của sự kiện có phải là null hay không, để đảm bảo rằng có tồn tại lớp đăng ký nhận sự kiện trước khi gọi sự kiện OnSecondChange. Chúng ta lưu ý rằng OnSecondChange lấy hai tham số: nguồn phát ra sự kiện và đối tượng dẫn xuất từ lớp EventArgs. Ở đây chúng ta có thể thấy rằng tham chiếu this của lớp clock được truyền bởi vì clock là nguồn phát ra sự kiện. Tham số thứ hai là đối tượng TimeInfo- EventArgs được tạo ra ở dòng lệnh bên trên. Một sự kiện được phát ra thì sẽ gọi bất cứ phương thức nào được đăng ký với lớp Clock thông qua delegate, chúng ta sẽ kiểm tra điều này sau. Một khi mà sự kiện được phát ra, chúng ta sẽ cập nhật lại trạng thái của lớp Class: this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; Sau cùng là chúng ta xây dựng những lớp có thể đăng ký vào các sự kiện này. Chúng ta sẽ tạo hai lớp. Lớp đầu tiên là lớp DisplayClock. Chức năng chính của lớp này không phải là lưu giữ thời gian mà chỉ để hiển thị thời gian hiện hành ra màn hình console. Để đơn giản chúng ta chỉ tạo hai phương thức cho lớp này. Phương thức thứ nhất có tên là Subscribe, phương thức chịu trách nhiệm đăng ký một sự kiện OnSecondChange của lớp Clock. Phương thức thứ hai được tạo ra là trình xứ lý sự kiện TimeHasChanged: public class DisplayClock { public void Subscrible(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged); }
  4. public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine(“Current Time: {0]:{1}:{2}”, ti.hour.ToString(), ti.minute.ToString(), ti.Second.ToString());
  5. } } Khi phương thức đầu tiên Subscribe được gọi, nó sẽ tạo ra một delegate SecondChange- Handler mới, và truyền vào phương thức xử lý sự kiện TimeHasChanged của nó. Sau đó nó sẽ đăng ký delegate với sự kiện OnSecondChange của Clock. Lớp thứ hai mà chúng ta tạo cũng sẽ đáp ứng sự kiện này, tên là LogCurrentTime. Thông thường lớp này ghi lại sự kiện vào trong tập tin, nhưng với mục đích minh họa của chúng ta, nó sẽ ghi ra màn hình console: public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); } // thông thường phương thức này viết ra file // nhưng trong minh họa này chúng ta chỉ xuất // ra màn hình console mà thôi public void WriteLogEntry( object theClock, TimeInfoEventArgs ti) { Console.WriteLine(“Logging to file: {0}:{1}:{2}”, ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } } Ghi chú rằng những sự kiện được thêm vào bằng cách sử dụng toán tử +=. Điều này cho phép những sự kiện mới được thêm vào sự kiện OnSecondChange của đối tượng Clock mà không có phá hủy bất cứ sự kiện nào đã được đăng ký. Khi LogCurrentTime đăng ký một sự kiện OnSecondChange, chúng ta không muốn việc đăng ký này làm mất đi sự đăng ký của lớp DisplayClock trước đó. Tất cả phần còn lại cần thực hiện là tạo ra một lớp Clock, tạo mộ đối tượng DisplayClock và bảo nó đăng ký sự kiện. Sau đó chúng ta tạo ra một đối tượng LogCurrentTime và cũng đăng
  6. ký sự kiện tương tự. Cuối cùng thì thực thi phương thức Run của Clock. Tất cả phần trên được trình bày trong ví ụ 11.4. Ví dụ 11.4: làm việc với những sự kiện. ----------------------------------------------------------------------------- namespace Programming_CSharp
  7. { using System; using System.Threading; // lớp lưu giữ thông tin về sự kiện, trong trường hợp // này nó chỉ lưu giữ những thông tin có giá trị lớp clock public class TimeInfoEventArgs : EventArgs { public TimeInfoEventArgs(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public readonly int hour; public readonly int minute; public readonly int second; } // khai báo lớp Clock lớp này sẽ phát ra các sự kiện public class Clock { // khai báo delegate mà các subscriber phải thực thi public delegate void SecondChangeHandler(object clock, TimeInfoEventArgs timeInformation); // sự kiện mà chúng ta đưa ra public event SecondChangeHandler OnSecondChange; // thiết lập đồng hồ thực hiện, sẽ phát ra mỗi sự kiện trong mỗi giây public void Run() { for(;;) { // ngừng 10 giây Thread.Sleep( 10 ); // lấy thời gian hiện hành System.DateTime dt = System.DateTime.Now; // nếu giây thay đổi cảnh báo cho subscriber if ( dt.Second != second) {
  8. // tạo TimeInfoEventArgs để truyền // cho subscriber TimeInfoEventArgs timeInformation = new TimeInfoEventArgs( dt.Hour, dt.Minute, dt.Second); // nếu có bất cứ lớp nào đăng ký thì cảnh báo if ( OnSecondChange != null) { OnSecondChange( this, timeInformation); } } // cập nhật trạng thái this.second = dt.Second; this.minute = dt.Minute; this.hour = dt.Hour; } } private int hour; private int minute; private int second; } // lớp DisplayClock đăng ký sự kiện của clock. // thực thi xử lý sự kiện bằng cách hiện thời gian hiện hành public class DisplayClock { public void Subscrible(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(TimeHasChanged); } public void TimeHasChanged( object theClock, TimeInfoEventArgs ti) { Console.WriteLine(“Current Time: {0}:{1}:{2}”, ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); }
  9. }
  10. // lớp đăng ký sự kiện thứ hai public class LogCurrentTime { public void Subscribe(Clock theClock) { theClock.OnSecondChange += new Clock.SecondChangeHandler(WriteLogEntry); } // thông thường phương thức này viết ra file // nhưng trong minh họa này chúng ta chỉ xuất // ra màn hình console mà thôi public void WriteLogEntry( object theClock, TimeInfoEventArgs ti) { Console.WriteLine(“Logging to file: {0}:{1}:{2}”, ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString()); } } // lớp Test minh họa sử dụng sự kiện public class Test { public static void Main() } { } // tạo ra đối tượng clock } Clock theClock = new Clock(); // tạo đối tượng DisplayClock đăng ký // sự kiện và xử lý sự kiện DisplayClock dc = new DisplayClock(); dc.Subscribe(theClock); // tạo đối tượng LogCurrent và yêu cầu đăng // ký và xử lý sự kiện LogCurrentTime lct = new LogCurrentTime(); lct.Subscribe(theClock); // bắt đầu thực hiện vòng lặp và phát sinh sự kiện // trong mỗi giây đồng hồ theClock.Run();
  11. được phân ------------------------------ tách ------------------------------ bởi ----------------- deleg Kết quả thực hiện có ate, thể như sau: đây là một Current Time: 11:54:20 sự Logging to file: 11:54:20 mong đợi Current Time: 11:54:21 cao, Logging to file: 11:54:21 nó Current Time: 11:54:22 làm cho Logging to file: 11:54:22 mã ------------------------------ lện ------------------------------ ----------------- h Điều quan trọng chính lin của ví dụ minh họa trên là h việc tạo ra hai lớp đối họ tượng DisplayClock at và lớp LogCurrentTime. và Cả hai lớp này đều đăng mạ ký một sự kiện nh Clock.OnSecondChange mẽ của lớp thứ ba là lớp hơ Clock n. Lợi ích của cơ chế Lớ publish/subscribe là bất p cứ lớp nào cũng có thể Cl được cảnh báo khi một oc sự kiện xuất hiện. k Những lớp subscriber có không cần biết cách mà thể Clock làm việc, và tha Clock cũng không cần y biết cách mà các lớp đổi subscriber đáp ứng với các sự kiện mà nó đưa ra. h Publisher và subscriber
  12. dò thời gian mà không nhi làm ảnh hưởng đến bất ệm cứ lớp subscriber nào. vụ Các lớp subscriber có nh thể thay đổi cách mà ư chúng đáp ứng với sự mộ thay đổi của thời gian t mà không tác động với ủy Clock. Cả hai lớp này qu hoạt động độc lập với yề nhau, và làm cho đoạn n. chương trình dễ duy trì Tu hơn. y Câu hỏi và trả lời nhi ên, Câuhỏi 1: Tóm tắt những nét cơ bản về uỷ quyền? co Trả lời 1: Ủy quyền là n một kiểu dữ liệu tham trỏ chiếu đươc dùng để hà đóng gói phương thức m với các tham số và kiểu tro trả về xác định. Ủy ng quyền cũng tương tự C/ như con trỏ hàm trong C ngôn ngữ C++. Tuy + nhiên, trong ngôn ngữ + C# ủy quyền là kiểu dữ đơ liệu hướng đối tượng, n an toàn giả và bảo mật. n Câuhỏi 2: Con trỏ hàm là kh gì? ôn Trả lời 2: Trong ngôn ngữ g như C hay C++, có một ph chức năng gọi là con trỏ ải hàm. Một con là trỏ hàm được sử dụng mộ để thiết lập cùng một
  13. t đối tượng. Còn ủy Câu quyền trong C# là kiểu hỏi 6: dữ liệu an toàn, được Các dùng để tham chiếu đến toán những phương thức, ủy tử nào quyền còn được sử có dụng thể bởi những sự kiện. dùn g để Câu hỏi thêm thực hiện Câu hỏi 1: Có thể sử dụng việc ủy quyền như một thuộc Mul tính hay không? Nếu có tica st thể thì sử dụng như thế các nào? Cho biết ý nghĩa? ủy Câuhỏi 2: Nếu có một số quy hoạt động cần được thực ền? hiện theo một thứ tự nhất C định thì ta phải â làm thế nào để khi cần thực hiện thì gọi lần lượt u thực hiện các hoạt động h đó? ỏ Câu hỏi 3: Công dụng của i việc khai báo ủy quyền 7 tĩnh? Khi nào thì nên khai : báo ủy quyền tĩnh khi nào thì không nên? S Câuhỏi 4: Một ủy quyền có ự thể gọi được nhiều hơn một phương thức hay k không? Chức năng nào i trong C# hỗ trợ ủy quyền ệ này? n Câu hỏi 5: Có phải tất cả các ủy quyền đều là ủy l quyền Multicast hay à không? Điều kiện để trở thành ủy quyền Multicast? g
  14. ì? Trong hệ thống ứng dụng nào thì sự kiện được sử dụng nhiều? Câuhỏi 8: Những sự kiện trong C# được thực hiện thông qua cái gì? Câu hỏi 9: Hãy tóm lược quá trình tạo một sự kiện và giải quyết sự kiện thông qua cơ chế ủy quyền trong C#? Bài tập Bài tập 1: Viết chương trình minh họa sử dụng ủy quyền để thực hiện việc sắp xếp các số nguyên trong một mảng? Bài tập 2: Viết chương trình minh họa sử dụng ủy quyền để thực hiện việc chuyển các ký tự thường thành ký tự hoa trong một chuỗi? Bài tập 3: Viết chương trình kết hợp giữa delegate và sự kiện để minh họa một đồng hồ điện tử thể hiện giờ hiện hành trên màn hình console.
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2