Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 16 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
16
Dung lượng
122,53 KB
Nội dung
Những chủ đề tiến bộ trong C# Events ( Các sự kiện) Khi một ứng dụng chạy trên nền window nhận các thông báo khi môt việc gì đó xảy ra ta gọi đó là event . ví dụ khi ta nhấn nút chuột thì cửa sổ ứng dụng mà ta nhấn sẽ được thông báo event này . Trong C# , các event thực sự là 1 dạng đặc biệt của delegate Tuy nhiên ta không cần quan tâm các delegate bên dưới làm gì . ta sẽ tiếp cận event trên quan điểm phần mềm client ( client software). ta sẽ tập trung vào phần mã cần viết để nhận các thông báo của event ,không cần quan tâm bên dưới làm gì . các event trong C# hơi giống với các khái niệm của VB mặc dù cú pháp và các thực thi bên dưới thì không giống. Consumer's view of event ( Cách nhìn của consumer về các event) Consumer ở đây là các ứng dụng mà muốn được thông báo khi điều gì đó xảy ra.cũng có thể là các phần mềm khác( thường là hệ điều hành window hay .NET Framework ). ta xem các phần mềm khác này là bộ phát sinh event ( event generator) Ở nơi nào đó trong consumer sẽ có 1 phương thức mà sẽ được gọi khi 1 MouseClick xaỷ ra.phương thức này đưọc gọi là event handler ( bộ xử lí event) cho event và 1 tên hay hơn cho nó trong trường hợp này là OnClick() .để gửi đến bộ phát sinh event thông tin này ,consumer sẽ phải đặt 1 tham chiếu đến OnClick() vào bên trong 1 delegate. mỗi lần bộ phát sinh event có thông tin này ,khi thăm dò thấy chuột được nhấn, nó dùng delegate này để gọi phương thức Onclick() của Consumer. Tất cả các bộ xử lí event phải trông giống như sau: void OnClick(object sender, EventArgs e) // e cũng có thể được dẫn xuất từ EventArgs { // mã xửlí event } Bộ xử lí event chỉ có thể trả về void.tất cả những gì bộ phát sinh event muốn làm là gọi 1 phương thức. không cần biết consumer làm gì để đáp ứng.các bộ xử lí phải lấy 2 thông số. thông số đầu là 1 tham chiếu đến đối tượng sinh ra event. thông số thứ 2 phải là 1 tham chiếu đến lớp cơ sở .NET , System.EvetnArgs ,hoặc là 1 lớp dẫn xuất từ nó.1 lớp dẫn xuất có thể chứa thông tin thêm về event như vị trí chuột ,phím nào được nhấn trên bàn phím. Để báo cho bộ phát sinh event biết ta quan tâm đến event. ta cần bộ phát sinh event tạo 1 vài mục mà có thể nhận các yêu cầu cho thông báo. mục này sẽ là thành viên public của lớp .NET mà đại diện cho bộ phát sinh event,và là thành viên của kiểu event . thành viên này là 1 dạng đặc biệt của multicast delegate.ta giả sử rằng consumer có 1 tham chiếu đến bộ phát sinh event, qua trung gian là 1 biến tham chiếu gọi là Generator, và đó là thành viên mà đại diện cho event được gọi là MouseClick. trong lớp consumer ,ta viết : EventGenerator Generator = GetAReferenceToTheEventGeneratorSomehow(); Ta giả sử rằng EventGenerator đại diện cho lớp bộ phát sinh event consumer có thể thông báo với bộ phát sinh event rằng nó muốn nhận thông báo về việc nhấn chuột bằng dòng mã sau : Generator là 1 tham chiếu đến bộ phát sinh event Generator.MouseClick += OnClick(); Khi bộ phát sinh event không quan tâm đến event này nữa ta có thể thông báo cho bộ phát sinh event như sau : Generator.MouseClick -= OnClick(); Consumer của ta có thể yêu cầu các thông báo của nhiều event mà nó muốn, thậm chí là yêu cầu các thông báo từ các nguồn khác.vì vậy mà thông số đầu tiên được truyền đến bộ xử lí event là tham chiếu sender .ví dụ như trong một ứng dụng win form ta có nhiều nút nhấn , tất cả các nút đều có thể thông báo khi nó bị nhấn , bằng cách kiểm tra tham chiếu sender ta có thể biết được nút nào được nhấn. ngoài ra các consumer khác nhau có thể yêu cầu được thông báo các event giống nhau.đơn giản chỉ việc cộng bộ xử lí event của nó vào các event bởi vì theo cách các multicast delegate làm việc , thì khi event được bắt, tất cả các bộ xử lí event sẽ được kích. Ví dụ về các Event : Console Notifications Ta sẽ xem xét ví dụ UserInputNotify.trong ví dụ này ta xét lại công ty điện thọai Mortimer Phones . ta sẽ viết 1 đoạn chương trình console nhỏ trình bày 1 thông điệp đến người dùng. trong ví dụ người dùng sẽ chọn lựa giữa việc xem 1 thông điệp riêng từ Mortimer hay 1 quảng cáo chung. chương trình sẽ tiếp tục hỏi người dùng thông điệp muốn thấy cho đến khi nguời dùng gõ X và nhấn Enter để thoát chương trình. tuy nhiên ta sẽ sắp xếp lại cấu trúc chương trình để dùng các event. Có 2 đối tượng cần quan tâm trong mã của ta : UserInputMonitor -đây là đối tượng mà tiếp xúc với người dùng . nó chịu trách nhiệm hỏi nguời dùng thông điệp họ muốn thấy. MessageDisplayer - đây là đối tượng mà chịu trách nhiệm cho việc trình bày thông điệp tương ứng. Bởi vì phần trình bày thông điệp không liên quan đến việc người dùng nhập , nên nó không biết khi nào sẽ trình bày thông điệp hay thông điệp nào sẽ được trình bày - do đó nó cần nhờ đến UserInputMonitor . UserInputMonitor sẽ làm điều này bằng cách đưa ra 1 event. MessageDisplayer sẽ thông báo UserInputMonitor mà nó muốn được bảo khi người dùng yêu cầu trình bày thông điệp .sau đó khi người dùng tạo ra một yêu cầu ,UserInputMonitor sẽ đưa ra 1 event tương ứng, làm cho MessageDisplayer được gọi trong bộ xử lí event. 1 lớp khác ManagersStaffMonitor, mà sẽ bảo Motimer khi ai đó yêu cầu để xem thông điệp riêng của anh ấy. cho mục đích này ManagersStaffMonitorsẽ trình bày 1 hộp thoại nói Kaark! .ta thấy kiến trúc event thích hợp làm điều này bởi vì tất cả những gì ta phải làm là để Mortimer biết về event đưọc đặt trong bộ xử lí event riêng của ManagersStaffMonitor vào trong event . khi 1 khách hàng yêu cầu xem thông điệp thì event sẽ gọi cả hai bộ xử lí event liên tiếp nhau . nếu 1 phần mềm khác muốn được thông báo event này , nó sẽ làm cùng việc sau : viết 1 bộ xử lí event và thêm nó đến event trong UserInputMonitor. theo cách này , bộ xử lí event có thể được nối với nhau. cấu trúc của chương trình ta sẽ như sau : Trong biểu đồ trên ,ta đánh dấu trong bộ xử lí event cho lớp consumer, MessageDisplayer và ManagersStaffMonitor, cũng như event trong lớp bộ phát sinh event của ta UserInputMonitor. để truyền chi tiết của event ,ta sẽ dùng 1 lớp mới ,UserRequestEventArgs, mà ta sẽ dẫn xuất từ System.EventArgs , mà sẽ thi hành 1 thuộc tính,Request .cho biết người dùng chọn đề nghị nào. Đầu tiên ta viết lớp UserRequestEventArgs ,ta sẽ dùng 1 bảng liệt kê để liệt kê các event có thể có : enum RequestType {AdRequest, PersonalMessageRequest}; class UserRequestEventArgs : EventArgs { private RequestType request; public UserRequestEventArgs(RequestType request) : base() { this.request = request; } public RequestType Request { get { return request; } } } Ta đơn giản thêm 1 trường và thuộc tính chỉ định người dùng chọn đề nghị nào. tiếp theo ta xây dựng bộ phát sinh event ,UserInputMonitor: class UserInputMonitor { public delegate void UserRequest(object sender, UserRequestEventArgs e); public event UserRequest OnUserRequest; public void Run() { bool finished = false; do { Console.WriteLine("Select preferred option:"); Console.WriteLine(" Request advertisement - hit A then Return"); Console.WriteLine(" Request personal message from Mortimer " + "- hit P then Return"); Console.WriteLine(" Exit - hit X then Return"); string response = Console.ReadLine(); char responseChar = (response == "") ? ' ' : char.ToUpper(response[0]); switch(responseChar) { case 'X': finished = true; break; case 'A': OnUserRequest(this, new UserRequestEventArgs(RequestType.AdRequest)); break; case 'P': OnUserRequest(this, new UserRequestEventArgs(RequestType.PersonalMessageRequest)); break; } } while (!finished); } } Lớp này chứa chỉ 1 dòng mã mà ta thực sự dùng từ khoá event để khai báo 1 event. 2 dòng mã ta quan tâm là : public delegate void UserRequest(object sender, UserRequestEventArgs e); public event UserRequest OnUserRequest; Đầu tiên ta định nghĩa delegate và sau đó khai báo 1 thể hiện của nó.lưu ý rằng nó phải trả vế 1 void, và lấy 1 object và 1 thông số dẫn xuất từ EvenArgs . Dòng thứ 2 ta bảo trình biên dịch rằng lớp này chứa 1 event thành viên, có kiểu là delegate. Phần cuối của lớpUserInputMonitor đưa ra phương thức run() , mà tạo vòng lặp yêu cầu ngưòi dùng nhập.chú ý cách mà event được bắt : switch(responseChar) { [...]... inputMonitor = new UserInputMonitor(); MessageDisplayer inputProcessor = new MessageDisplayer(inputMonitor); ManagersStaffMonitor mortimer = new ManagersStaffMonitor(inputMonitor); inputMonitor.Run(); } } Nếu viết đúng ta có kết quả : UserInputNotify Select preferred option: Request advertisement - hit A then Return Request personal message from Mortimer - hit P then Return Exit - hit X then Return A Mortimer... MessageDisplayer { public MessageDisplayer(UserInputMonitor monitor) { monitor.OnUserRequest += new UserInputMonitor.UserRequest(UserRequestHandler); } protected void UserRequestHandler(object sender, UserRequestEventArgs e) { switch (e.Request) { case RequestType.AdRequest: Console.WriteLine("Mortimer Phones is better than anyone " + "else because all our software is written in C#! \n"); break; case RequestType.PersonalMessageRequest:... RequestType.PersonalMessageRequest: Console.WriteLine("Today Mortimer issued the following " + "statement:\n Nevermore!\n"); break; } } } Hàm dựng của MessageDisplayer ta muốn nhận các thông báo event từ lớp UserInputMonitor ta làm bằng cách thêm vào 1 tham chiếu bộ xử lí event đến event UserRequest bộ xử lí event là phương thức UserRequestHandler() ,nó kiểm tra thông số EventArgs để xem kiểu thông... void UserRequestHandler(object sender, UserRequestEventArgs e) { if (e.Request == RequestType.PersonalMessageRequest) { MessageBox.Show("Kaark!", "Mortimer says "); } } } Cuối cùng ta có thể thấy các lớp hợp với nhau ,và được dùng trong đoạn mã chính sau : using System; using System.Windows.Forms; namespace Wrox.ProCSharp.AdvancedCSharp { class MainEntryPoint { static void Main() { UserInputMonitor... finished = true; break; case 'A': OnUserRequest(this, new UserRequestEventArgs(RequestType.AdRequest)); break; case 'P': OnUserRequest(this, new UserRequestEventArgs(RequestType.PersonalMessageRequest)); break; } Ta đơn giản gọi event mà tự động thực thi bất kì phương thức nào nó tham chiếu trong mỗi trường hợp ta khởi tạo 1 lớp dẫn xuất EventArgs mới để truyền đến bộ xử lí event Tiếp theo là lớp consumer... ý ta tạo bộ xử lí event là protected vì chúng không được gọi trực tiếp nên các lớp bên ngoài không nên nhìn thấy chúng Lớp ManagersStaffMonitor riêng của Mortimer làm giống như vậy , ngoại trừ nó trình bày 1 hộp thoại thay cho viết ra màn hình đen : class ManagersStaffMonitor { public ManagersStaffMonitor(UserInputMonitor monitor) { monitor.OnUserRequest += new UserInputMonitor.UserRequest(UserRequestHandler);... Mortimer - hit P then Return Exit - hit X then Return A Mortimer Phones is better than anyone else because all our software is written in C#! Select preferred option: Request advertisement - hit A then Return Request personal message from Mortimer - hit P then Return Exit - hit X then Return P Today Mortimer issued the following statement: Nevermore! with the Windows Form when the user hits P looking like . Những chủ đề tiến bộ trong C# Events ( Các sự kiện) Khi một ứng dụng chạy trên nền window nhận các thông báo khi môt việc gì đó xảy ra ta gọi. này . Trong C# , các event thực sự là 1 dạng đặc biệt của delegate Tuy nhiên ta không cần quan tâm các delegate bên dưới làm gì . ta sẽ tiếp cận event trên quan điểm phần mềm client ( client. vào phần mã cần viết để nhận các thông báo của event ,không cần quan tâm bên dưới làm gì . các event trong C# hơi giống với các khái niệm của VB mặc dù cú pháp và các thực thi bên dưới thì không