Multicast delegate's invocation Các method khác được thêm vào danh sách gọi của multicast delegate bằng toán tử gán '+=‘ Ví dụ MyMulticastDelegate arithMethod = null; arithM
Trang 1Chapter 4
Delegate & Event
Trang 2 Khái niệm event
Event & delegate
Cơ chế publishing & subscribing
Minh họa cơ chế event
Trang 3Delegate là gì
Delegate là 1 kiểu dữ liệu loại tham chiếu cho phép lưu trữ các tham chiếu đến hàm.
Trang 4Delegate
Delegates tương tự như tham chiếu đối tượng, nhưng
được dùng để tham chiếu method thay vì tham chiếu đối tượng
Khái niệm delegate tương tự như con trỏ hàm trong C++.
Trang 5Khai báo delegate
Delegate được khai báo giống như khai báo hàm nhưng không có phần thân hàm Khai báo delegate xác định loại dữ liệu trả về (return type) và danh sách các đối số
Trang 6Khởi tạo biến delegate
Sau khi khai báo delegate, có thể khai báo biến có kiểu là delegate vừa khai báo
Vi dụ: ProcessDelegate process;
Khởi đầu biến như 1 tham chiếu đến bất kỳ hàm nào có cùng kiểu trả về (return type) và danh sách đối số
(parameter list) như của delegate
Ví dụ: Nếu hàm Multiply có cùng signature với delegate có tên là process
static double Multiply(double param1, double param2)
{ return param1 * param2; }
Khởi tạo biến process
process = new ProcessDelegate( Multiply) ;
Trang 7Thực thi delegate
Khi đã khởi đầu biến, có thể gọi hàm thông qua biến delegate như thể nó là 1 hàm.
Ví dụ:
Console.WriteLine("Result: {0}",
process(13.5, 67));
Trang 8The type or signature of the method
int aMethod(int p, int q)
Signature of these two methods:
int aMethod(int p, int q)
define the type of a delegate using the delegate keyword
delegate int MyDelegate(int p, int q);
Trang 9The type or signature of the method
the delegate
can point to
define the type of a delegate using the delegate keyword
delegate int MyDelegate(int p, int q);
The reference of this delegate type can be used
to point to any method which takes two integers
as parameters and returns an integer value
Trang 10Biến delegate trong C#
In C# 1.0 and later, delegates can be declared as shown
here:
In C# 2.0 and later, it is also possible to use an anonymous method to declare and initialize a delegate by using this simplified syntax:
public delegate void Del<T>(T item);
public void Notify(int i) { }
Del<int> d1 = new Del<int>(Notify);
Del< int> d2 = Notify;
Trang 11Passing delegates to methods
Tham chiếu delegate của 1 method có thể được chuyển (pass) vào 1 method khác
static void PerformArithOperation(double a, double b,
processDelegate arithOperation ) {
double r = arithOperation(a, b);
Console.WriteLine("\nThe result of arithmetic
operation on 3 and 4 is: {0}", r); }
Method này được gọi như sau:
PerformArithOperation(3, 4, arithMethod);
Trang 12kế thừa từ System.Delegate type
A delegate is a reference type derived from
System.Delegate and its instances can be
used to call methods with matching
signatures.
Trang 13nghĩa bên trong 1 method
Ví dụ: định nghĩa delegate MyDelegate phải đặt ngoài
method Main()
class Test
{
delegate int MyDelegate(int p, int q);
static void Main()
Trang 14Multicast Delegates
Một delegate có thể chứa nhiều hơn 1
method có cùng signature.
Loại delegate này được gọi là multicast
delegate
Multicast delegate la loại con của
System.MulticastDelegate , mà chính nó lại là lớp con của System.Delegate
"The return type of a multicast delegate type must be void "
Trang 15Thực thi Multicast Delegate
Được khai báo giống như khai báo delegate thông thường nhưng kiểu trả về phải là void
delegate void MyMulticastDelegate(int p, int q);
Trang 16Multicast delegate's
invocation
Các method khác được thêm vào danh sách gọi của
multicast delegate bằng toán tử gán '+=‘
Ví dụ
MyMulticastDelegate arithMethod = null;
arithMethod = new MyMulticastDelegate(Add);
arithMethod += new MyMulticastDelegate(Subtract); arithMethod += new MyMulticastDelegate(Max);
Phép gọi (invocation) của multicast delegate tương tự
như delegate thông thường
arithMethod(3, 4);
Trang 1717
Trang 18Xây dựng hàm Sort tổng quát cho mảng đối tượng có kiểu
bất kỳ
Trang 19Solution
Phân tích
Nếu đối tượng là kiểu số như int, long, float thì ko có vấn đề
Trường hợp đối tượng phức khác?
So sánh theo
quy tắc nào
Trang 20Solution
Cho phép đối tượng tự quy định thứ tự
của chúng
Sử dụng delegate để truyền phương thức
so sánh này vào hàm Sort
void Sort(object[] list, CompareObj cmp)
Delegate này sẽ tham chiếu tới hàm Compare của lớp MyClass Chính lớp MyClass sẽ quy định thứ tự của các đối tượng
Trang 21Solution
Mô tả delegate CompareObj cho hàm Sort:
public delegate bool CompareObj (object o1,object o2)
Trả về true: nếu o1 “trước” o2
false: ngược lại
2 đối tượng cần so sánh
Tên của delegate
Trang 22Solution
public static void Sort(object[] objs, CompareObj public static void Sort(object[] objs, CompareObj cmp cmp )
{
for(int i=0; i < objs.Length-1; i++)
for(int j=objs.Length-1; j>i; j )
if ( cmp cmp ( objs[j], objs[j-1] ) )
{
Swap( objs[j], objs[j-1] );
} }
Định nghĩa hàm Sort tổng
quát cho các lớp
Delegate sẽ trỏ tới hàm Compare riêng của lớp tương ứng
Yêu cầu lớp tự
so sánh
Trang 23Solution
Các lớp hỗ trợ Sort thì phải
Cung cấp hàm Compare riêng
Signature phải thoả delegate CompareObj
Cùng signature
class Person {
private string name;
private int weight;
private int yearOfBirth;
public static bool CompareName(object p1, object p2) {
if (string.Compare(((Person)p1).name, ((Person)p2).name)<0) return true;
return false;
}
}
Trang 24Solution
public delegate bool CompareObj (object o1,object o2);
…
Person[ ] persons = new Person[4];
persons[0] = new Person(“ Quy Mui ", 2, 2004);
persons[1] = new Person(“ Ha Giang ", 65, 1978);
persons[2] = new Person(“ Ngoc Thao ", 47, 1979);
persons[3] = new Person(“ Ha Nam ", 65, 1932);
CompareObj cmp = new CompareObj (Person.CompareName);
HaGLib.Sort( persons, cmp );
Gọi hàm static Sort
Lớp chứa hàm Sort
Trang 25Event
Trang 26From delegate to event
So far we can invoke the delegate explicit.
But in many cases, it could be useful to have the delegate run automatically when something significant happens.
The Net framework provide the events, which you can
use to define and trap significant actions and arrange for
a delegate to be called to handle the situation
Trang 27Event
An event is a message sent by an object to signal the
occurrence of an action The action could be caused by user interaction, such as a mouse click, or it could be
triggered by some other program logic
The object that raises (triggers) the event is called the
event sender
The object that captures the event and responds to it is
called the event receiver
Trang 28Event trong GUI
Trong môi trường GUIs (Graphical User
Interfaces):
Các control phát ra sự kiện ( event sender)
Event-handling method (event receiver) sẽ đáp ứng lại các sự kiện do control phát
Khi sự kiện xảy ra, event sender sẽ gọi
event receiver để thực thi nhiệm vụ
Trang 29Event & Delegate
Trình xử lý sự kiện (eventHandler) trong NET Framework được mô tả như sau:
public delegate void EventHandler
( object sender, EventArgs e )
Tham số 1: nguồn phát sinh sự kiện
Tham số 2: EventArgs tham chiếu đến đối tượng các đối số sự kiện (event argument), chứa thông tin về sự kiện xảy
ra EventArgs là lớp cơ sở của tất cả class biểu diễn
thông tin về sự kiện
Phải thực hiện trình xử lý sự kiện theo đúng mẫu
trên!
Trang 30 Đối tương delegate giữ tham chiếu đến
method có cùng signature như khai báo của delegate
Các control của GUI đều có delegate được
định nghĩa sẵn tương đương với mỗi event
chúng phát ra
Trang 31delegate, event sender có thể gọi delegate phù hợp khi
sự kiện xảy ra.
Vi dụ: Button gọi delegate EventHandler để đáp ứng sự kiện click Để cho phép method clickButton_Click được gọi thì phải gán method này cho delegate bằng lệnh sau: this.button1.Click += new
System.EventHandler(this.button1_Click);
Trang 32Event delegate
Có thể xác định nhiều method khác nhau để đáp ứng cho cùng 1 sự kiện bằng cách thêm các delegate khác nhau.
Event delegates là multicast (một tập delegate có cùng
chung 1 signature) cho phép nhiều method được gọi để đáp ứng cùng 1 sự kiện Khi sự kiện xảy ra, evnet
sender gọi từng method được tham chiếu bởi multicast delegate
Inheritance Hierarchy
System Object
System Delegate
System MulticastDelegate
Trang 33Event Handling in C#
In Net, events are implemented as multicast delegates.
Steps for implementing events and event handling:
Step 1: Define a public delegate for the event outside any class
boundary
public delegate void EventDelegate(object sender, EventArgs
e)
Trang 34Event Handling in C#
Step 2:
- Define a class to generate or raise the event
class SomeEventArgs : EventArgs {
}
- Define a public event in the class
public event EventDelegate MyEvent
- An event is generally raised like this:
SomeEventArgs someData = new SomeEventArgs(/*some
necessary arguments*/);
MyEvent(this, someData);
Trang 35- Instantiate the event generator class created in step 2:
EventClass eventObj = new EventClass();
- Add the event handler written in the current class to the event generator class' event
eventObj.MyEvent += new EventDelegate(OnMyEvent);
Trang 36 Lớp A: hiển thị thời gian theo “mô phỏng đồng hồ analog”
Lớp B: hiển thị thời gian theo “mô phỏng đồng hồ digital”
Trang 37Minh họa 1
Tạo một lớp Clock:
Khai báo một event: OnSecondChange
Một phương thức Run: cứ 1s thì phát sinh sự kiện
OnSecondChange
Tạo 2 lớp: AnalogClock và DigitalClock nhận xử lý sự kiện OnSecondChange của lớp Clock
Trang 38Minh họa 1
Khai báo delegate xử lý event
delegate void
delegate void SecondChangeHandler SecondChangeHandler (object clock (object clock , EventArgs info , EventArgs info );
Tên delegate xử lý sự kiện
Đối tượng phát sinh event
Tham số kiểu EventArgs
Trang 39Tên của event
Từ khóa event: thể hiện cơ chế publishing & subscribing
Trang 40Minh họa 1
Kích hoạt sự kiện
if ( OnSecondChange != null)
OnSecondChange(this, new EventArgs());
Gọi hàm xử lý sự kiện đã đăng ký
Kiểm tra xem có hàm xử lý được đăng ký hay không?
Trang 41Minh họa 1
public class Clock {
public delegate void
SecondChangeHandler (object clock, EventArgs info); public event SecondChangeHandler OnSecondChange ;
public void Run() {
Trang 42Minh họa 1
Lớp DigitalClock
Định nghĩa trình xử lý sự kiện của Clock
Đăng ký xử lý với trình xử lý sự kiện trên khi có sự kiện
OnSecondChange của Clock
OnSencondChange của Clock phát sinh
DigitalClock
Trang 43Minh họa 1
Trình xử lý của DigitalClock
public void Show (object obj , EventArgs args)
Trang 44Minh họa 1
Đăng ký xử lý sự kiện (nhận sự kiện)
public void Subscribe(Clock public void Subscribe(Clock theClock theClock )
Trang 46Minh họa 1
Định nghĩa trình xử lý sự kiện của Clock
Đúng mô tả delegate hàm xử lý của lớp Clock
Thực hiện một số thao tác riêng của AnalogClock
Đăng ký xử lý với trình xử lý sự kiện trên khi có sự kiện OnSecondChange của Clock
Chức năng đăng ký với lớp Clock là có xử lý khi
sự kiện OnSencondChange của Clock phát sinh
Ủy thác cho lớp Clock sẽ gọi trình xử lý định
nghĩa bên trên của AnalogClock
Trang 48Minh họa 1
Minh họa cơ chế event
public class Tester {
public static void Main() {
Clock myClock = new Clock();
AnalogClock c1 = new AnalogClock();
DigitalClock c2 = new DigitalClock();
Trang 4949
Trang 50Minh họa EventArgs
Giải pháp:
Khi phát sinh sự kiện, truyền thời gian hiện hành lớp subscribing sẽ sử dụng tham số này
Tạo một lớp TimeEventArgs kế thừa từ
EventArgs: chứa thời gian sẽ truyền đi
Trang 51Minh họa EventArgs
Tạo lớp chứa tham số truyền cho trình xử lý sự kiện
Lớp dẫn xuất từ EventArgs
Chứa các thông tin về: giờ, phút, giây
Bắt buộc phải dẫn xuất từ EventArgs
Do mô tả của trình xử lý sự kiện là tham số thứ 2 phải là lớp dẫn xuất từ EventArgs!
Trang 52Minh họa EventArgs
public class TimeEventArgs : EventArgs
{
public readonly int Second;
public readonly int Minute;
public readonly int Hour;
public TimeEventArgs(int s, int m, int h)
Trang 53Minh họa EventArgs
Trong lớp Clock khai báo trình xử lý sự kiện như sau
public delegate void
SecondChangeHandler(object obj, TimeEventArgs arg);
Sử dụng tham số thứ hai có kiểu TimeEventArgs
Trang 54Minh họa EventArgs
Khi kích hoạt sự kiện thì truyền tham số {giờ, phút, giây}
public void Run( ) {
TimeEventArgs timeArg = new
TimeEventArgs(date.Second, date.Minute, date.Hour); OnSecondChange(this, timeArg);
}
}
}
Trang 55Minh họa EventArgs
Các lớp DigitalClock và AnalogClock: sử dụng tham số
Trang 56Minh họa EventArgs
Các phần khác còn lại tương tự như minh họa 1