Tài liệu Tìm hiểu C# và ứng dụng của C# p 16 pdf

8 347 0
Tài liệu Tìm hiểu C# và ứng dụng của C# p 16 pdf

Đang tải... (xem toàn văn)

Thông tin tài liệu

Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 94 12.1.2 Delegate tĩnh Điểm bất lợi của ví dụ 12-1 là nó buộc lớp gọi, trong trường hợp này là lớp Test , phải khởi tạo các delegate nó cần để sắp thứ tự các đối tượng trong một cặp. Sẽ tốt hơn nếu như có thể lấy các delegate từ lớp Dog Student . Chúng ta có thể làm điều này bằng cách tạo cho trong mỗi lớp một delegate tĩnh. Đối với lớp Student ta thêm như sau: public static readonly Pair.WhichIsFirst OrderStudents = new Pair.WhichIsFirst(Student.WhichStudentComesFirst); Dòng lệnh này tạo một delegate tĩnh, chỉ đọc có tên là OrderStudent Ta có thể tạo tương tự cho lớp Dog public static readonly Pair.WhichIsFirst OrderDogs = new Pair.WhichIsFirst(Dog. WhichDogComesFirst); Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 95 12.1.4 Thứ tự thực thi với mảng các các delegate Delegate có thể giúp ta xậy dựng một hệ thống cho phép người dùng có thể quyết định một cách động trình tự thực thi các thao tác. Giả sử chúng ta có hệ thống sử lý ảnh, hệ thống này có thể thao tác ảnh theo nhiều cách như: làm mờ (blur) ảnh, làm sắc nét, quay, lọc v.v…ảnh. Cũng giả sử rằng trình tự áp dụng các hiệu ứng trên ảnh hưởng lớn đến đến chất lượng của ảnh. Người dùng sẽ mong muốn chọn các hiệu ứng họ lẫn trình tự của chúng từ một thực đơn, sau đó hệ thống sẽ thực hiện các hiệu ứng này theo trình tự họ đã định. dùng hay không. Ta có thể cải tiến bằng cách thay đổi biến thành viên tĩnh thành delagate Một vấn đề với tĩnh là nó phải được khởi tạo trước, cho dù có được 12.1.3 Delegate như Property Kết quả hoàn toàn như ví dụ trên. dogPair.ToString( )); Console.WriteLine("After ReverseSort dogPair.ReverseSort(Dog.OrderDogs); dogPair.ToString( )); Console.WriteLine("After Sort dogPair\t\t: {0}", dogPair.Sort(Dog.OrderDogs); studentPair.ToString( )); Console.WriteLine("After ReverseSort studentPair\t: {0}", studentPair.ReverseSort(Student.OrderStudents); studentPair.ToString( )); Console.WriteLine("After Sort studentPair\t\t: {0}", studentPair.Sort(theStudentDelegate); truyền như tham số. Như vậy mỗi lớp có một delegate riêng, khi cần ta lấy các delegate này } get{ return new Pair.WhichIsFirst(WhichDogComesFirst);} { public static Pair.WhichIsFirst OrderDogs Dog Tương tự thay thế cho lớp } get{ return new Pair.WhichIsFirst(WhichStudentComesFirst); } { public static Pair.WhichIsFirst OrderStudents và thay thế bằng new Pair.WhichIsFirst(Student.WhichStudentComesFirst); public static readonly Pair.WhichIsFirst OrderStudents = , ta bỏ khai báo sau: Student Đối với lớp property delegate Khác biệt chính ở đây là sẽ chỉ được khởi tạo khi có yêu cầu. return new Pair.WhichIsFirst(WhichStudentComesFirst); OrderStudent delegate Khi property được truy cập, sẽ được tạo: Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 96 Ta có thể tạo một delegate cho mỗi thao tác (hiệu ứng) đẩy chúng vào một túi chứa có thứ tự, như một mảng chẳng hạn, theo đúng trình tự nó sẽ được thực thi. Khi tất cả các delegate được tạo thêm vào túi chứa, ta chỉ đơn giản duyệt suốt mảng, gọi các delegate khi tới lượt. Ta bắt đầu tạo lớp Image để đại diện cho một bức ảnh sẽ được xử lý bởi ImageProcessor : public class Image { public Image( ) { Console.WriteLine("An image created"); } } Lớp ImageProcessor khai báo một delegate không tham số trả về kiểu void public delegate void DoEffect( ); Sau đó khai báo một số phương thức để thao tác ảnh có nguyên mẫu hàm như delegate đã khai báo ở trên. public static void Blur( ) { Console.WriteLine("Blurring image"); } public static void Filter( ) { Console.WriteLine("Filtering image"); } public static void Sharpen( ) { Console.WriteLine("Sharpening image"); } public static void Rotate( ) { Console.WriteLine("Rotating image"); } Lớp ImageProccessor cần một mảng để giữ các delegate người dùng chọn; một biến để giữ số lượng hiệu ứng muốn xử lý hiển nhiên một bức ảnh image DoEffect[] arrayOfEffects; Image image; int numEffectsRegistered = 0; ImageProccessor cũng cần một phương thức để thêm delegate vào mảng public void AddToEffects(DoEffect theEffect) { if (numEffectsRegistered >= 10) { throw new Exception("Too many members in array"); } arrayOfEffects[numEffectsRegistered++] = theEffect; } Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 97 Một phương thức để gọi thực thi các hiệu ứng public void ProcessImages( ) { for (int i = 0;i < numEffectsRegistered;i++) { arrayOfEffects[i]( ); } } Cuối cùng ta khai báo các delegate tĩnh để client có thể gọi. public DoEffect BlurEffect = new DoEffect(Blur); public DoEffect SharpenEffect = new DoEffect(Sharpen); public DoEffect FilterEffect = new DoEffect(Filter); public DoEffect RotateEffect = new DoEffect(Rotate); Client sẽ có các đoạn mã để tương tác với người dùng, nhưng chúng ta sẽ làm lơ chuyện này, mặc định các hiệu ứng, thêm chúng vào mảng sau đó gọi ProcessImage Ví dụ 12-2. Sử dụng mảng các deleage using System; namespace Programming_CSharp { // ảnh ta sẽ thao tác public class Image { public Image( ) { Console.WriteLine("An image created"); } } public class ImageProcessor { // khai báo delegate public delegate void DoEffect( ); // tạo các delegate tĩnh gắn với các phương thức thành viên public DoEffect BlurEffect = new DoEffect(Blur); public DoEffect SharpenEffect = new DoEffect(Sharpen); public DoEffect FilterEffect = new DoEffect(Filter); public DoEffect RotateEffect = new DoEffect(Rotate); // hàm dựng khởi tạo ảng mảng public ImageProcessor(Image image) { this.image = image; arrayOfEffects = new DoEffect[10]; } public void AddToEffects(DoEffect theEffect) { if (numEffectsRegistered >= 10) { throw new Exception( "Too many members in array" ); } arrayOfEffects[numEffectsRegistered++] = theEffect; } // các hiệu ứng ảnh public static void Blur( ) Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 98 { Console.WriteLine("Blurring image"); } public static void Filter( ) { Console.WriteLine("Filtering image"); } public static void Sharpen( ) { Console.WriteLine("Sharpening image"); } public static void Rotate( ) { Console.WriteLine("Rotating image"); } public void ProcessImages( ) { for (int i = 0;i < numEffectsRegistered;i++) { arrayOfEffects[i]( ); } } // các biến thành viên private DoEffect[] arrayOfEffects; private Image image; private int numEffectsRegistered = 0; } // lớp kiểm thử public class Test { public static void Main( ) { Image theImage = new Image( ); // không giao diện để làm đơn giản vấn đề ImageProcessor theProc = new ImageProcessor(theImage); theProc.AddToEffects(theProc.BlurEffect); theProc.AddToEffects(theProc.FilterEffect); theProc.AddToEffects(theProc.RotateEffect); theProc.AddToEffects(theProc.SharpenEffect); theProc.ProcessImages( ); } } } Kết quả: An image created Blurring image Filtering image Rotating image Sharpening image Trong lớp Test , ImageProcessor được khởi tạo các hiệu ứng được thêm vào. Nếu người dùng chọn làm mờ ảnh (blur) trước khi lọc ảnh (filter), chỉ cần đơn giản thay đổi thứ tự của chúng trong mảng Tương tự, bất kỳ một hiệu ứng nào cũng có thể được lặp lại bằng cách thêm vào túi chứa delegate nhiều lần. Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 99 12.1.5 Multicasting Multicasting là cách để gọi hai phương thức thông qua một delegate đơn. Điều này sẽ trở nên quan trọng khi quản lý các sự kiện. Mục tiêu chính là để có một delegate đơn có thể gọi nhiều phương thức cùng một lúc. Nó khác với mảng các delagte , trong mảng delegate mỗi delegate chỉ gọi một phương thức. Ví dụ trước dùng một mảng làm túi chứa nhiều delegate khác nhau. Với multicasting ta có thể tạo một delegate đơn đóng gói nhiều phương thức. Ví dụ khi một button được nhấn, ta hằn muốn thao tác nhiều hành động cùng một lúc. Ta có thể cài đặt điều này bằng cách cho mỗi button một mảng các delegate , nhưng sẽ dễ hơn rõ nghĩa hơn khi tạo một multicasting delegate . Bất kỳ một delegate nào trả về void đều là multicast delegate , mặc dù ta có thể đối xử nó như single cast delegate (là delegate đề cập ở phần trên) nếu muốn. Hai multicast delegate có thể kết nối với nhau bằng toán tử cộng (+). Kết quả là một multicast delegate mới đóng gói tất cả các phương thức của hai delegate toán hạng. Ví dụ, giả sử Writer Logger là các delegate trả về kiểu void , dòng lệnh sau sẽ kết nối chúng tạo ra một multicast delegate mới có tên là myMulticastDelegate myMulticastDelegate = Writer + Logger; Ta cũng có thể thêm một delegate vào một multicast delegate bằng toán tử cộng bằng (+=). Giả sử ta có Transmitter myMulticastDelegate là các delegate , dòng lệnh sau: myMulticastDelegate += Transmitter; tương tự như dòng: myMulticastDelegate = myMulticastDelegate + Transmitter; Để xem cách multicast delegate được tạo sử dụng, xem qua toàn bộ ví dụ 12-3. Trong ví dụ này ta tạo một lớp tên là MyClassWithDelegate , lớp này định nghĩa một delegate nhận một tham số kiểu chuỗi trả về kiểu void . public delegate void StringDelegate(string s); Sau đó ta định nghĩa một lớp tên là MyImplementingClass có ba phương thức, tấ cả đều trả về void nhận một tham số kiểu chuỗi: WriteString , LogString và TransmitString. Phương thức đầu viết một chuỗi ra màn hình (đầu ra chuẩn), phương thức thứ hai viết ra tập tin lỗi (log file) phương thức thứ ba chuyển chuỗi lên Internet. Ta tạo các delegate để gọi các phương thức thích hợp. Writer("String passed to Writer\n"); Logger("String passed to Logger\n"); Transmitter("String passed to Transmitter\n"); Để xem cách kết hợp các delegate ta tạo ra một delegate khác MyClassWithDelegate.StringDelegate myMulticastDelegate; Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 100 và gán nó bằng kết quả của phép cộng hai delegate đã tồn tại myMulticastDelegate = Writer + Logger; Ta cũng có thể thêm bằng toán tử cộng bằng myMulticastDelegate += Transmitter; Cuối cùng ta có thể bỏ một delegate bằng toán tử trừ bằng (-=) DelegateCollector -= Logger; Ví dụ 12-3. Kết hợp các delegate using System; namespace Programming_CSharp { public class MyClassWithDelegate { // khai báo delegate public delegate void StringDelegate(string s); } public class MyImplementingClass { public static void WriteString(string s) { Console.WriteLine("Writing string {0}", s); } public static void LogString(string s) { Console.WriteLine("Logging string {0}", s); } public static void TransmitString(string s) { Console.WriteLine("Transmitting string {0}", s); } } public class Test { public static void Main( ) { // định nghĩa ba đối tượng StringDelegate MyClassWithDelegate.StringDelegate Writer,Logger,Transmitter; // định nghĩa một SringDelegate khác // hành động như một multicast delegate MyClassWithDelegate.StringDelegate myMulticastDelegate; // khởi tạo 3 delegate đầu tiên, // truyền vào các phương thức định đóng gói Writer = new MyClassWithDelegate.StringDelegate( MyImplementingClass.WriteString); Logger = new MyClassWithDelegate.StringDelegate( MyImplementingClass.LogString); Transmitter = new MyClassWithDelegate.StringDelegate( MyImplementingClass.TransmitString); // gọi phương thức của delegate Writer Writer("String passed to Writer\n"); // gọi phương thức của delegate Logger Logger("String passed to Logger\n"); // gọi phương thức của delegate Transmitter Transmitter("String passed to Transmitter\n"); // thông báo kết nối hai deleagte Delegate Event Gvhd: Nguyễn Tấn Trần Minh Khang 101 // thành một multicast deleagte Console.WriteLine("myMulticastDelegate = Writer + Logger"); // kết nối hai deleagte // thành một multicast deleagte myMulticastDelegate = Writer + Logger; // gọi delegated, hai phương thức được gọi myMulticastDelegate("First string passed to Collector"); // thông báo thêm deleagte thứ ba // vào một multicast deleagte Console.WriteLine("\nmyMulticastDelegate += Transmitter"); // thêm delegate thứ ba myMulticastDelegate += Transmitter; // gọi delegate, ba phương thức được gọi myMulticastDelegate("Second string passed to Collector"); // thông báo loại bỏ delegate logger Console.WriteLine("\nmyMulticastDelegate -= Logger"); // bỏ delegate logger myMulticastDelegate -= Logger; // gọi delegate, hai phương htức còn lại được gọi myMulticastDelegate("Third string passed to Collector"); } } } Kết quả: Writing string String passed to Writer Logging string String passed to Logger Transmitting string String passed to Transmitter myMulticastDelegate = Writer + Logger Writing string First string passed to Collector Logging string First string passed to Collector myMulticastDelegate += Transmitter Writing string Second string passed to Collector Logging string Second string passed to Collector Transmitting string Second string passed to Collector myMulticastDelegate -= Logger Writing string Third string passed to Collector Transmitting string Third string passed to Collector … Sức mạnh của multicast delegate sẽ dễ hiểu hơn trong khái niệm event . . các hiệu ứng, thêm chúng vào mảng và sau đó gọi ProcessImage Ví dụ 12-2. Sử dụng mảng các deleage using System; namespace Programming_CSharp { //. ImageProcessor theProc = new ImageProcessor(theImage); theProc.AddToEffects(theProc.BlurEffect); theProc.AddToEffects(theProc.FilterEffect); theProc.AddToEffects(theProc.RotateEffect);

Ngày đăng: 21/01/2014, 06:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan