Khái niệm cơ bản
- Event: Cơ chế cho phép class/đối tượng thông báo cho các class/đối tượng khác khi có sự kiện xảy ra.
- Publisher (Người phát hành): Class raise event.
- Subscriber (Người đăng ký): Class xử lý event.
Đặc điểm quan trọng
- Có thể có nhiều subscriber cho một event.
- Một subscriber có thể xử lý nhiều event từ nhiều publisher khác nhau.
- Event không có subscriber sẽ không bao giờ được raise.
- Publisher quyết định khi nào raise event; Subscriber quyết định hành động gì khi event xảy ra.
Ví dụ hoàn chỉnh: Video Encoder với nhiều Subscriber
using System;
using System.Threading;
// EventArgs tùy chỉnh
public class MP4
{
public string Title { get; set; }
}
public class MP4Args : EventArgs
{
public MP4 Video { get; set; }
}
// Publisher
public class MP4Encoder
{
// Định nghĩa event dùng EventHandler chuẩn
public event EventHandler<MP4Args> VideoEncoded;
public void Encode(MP4 video)
{
Console.WriteLine("Đang encode video...");
Thread.Sleep(1000); // Giả lập xử lý
OnVideoEncoded(video);
}
protected virtual void OnVideoEncoded(MP4 video)
{
VideoEncoded?.Invoke(this, new MP4Args { Video = video });
}
}
// Subscriber 1: Gửi email
public class MailService
{
public void OnVideoEncoded(object sender, MP4Args e)
{
Console.WriteLine($"[MailService] Gửi email cho video: {e.Video.Title}");
}
}
// Subscriber 2: Gửi tin nhắn
public class MessageService
{
public void OnVideoEncoded(object sender, MP4Args e)
{
Console.WriteLine($"[MessageService] Gửi tin nhắn cho video: {e.Video.Title}");
}
}
// Subscriber 3: Log
public class LogService
{
public void OnVideoEncoded(object sender, MP4Args e)
{
Console.WriteLine($"[LogService] Log: Video {e.Video.Title} đã encode xong lúc {DateTime.Now}");
}
}
class Program
{
static void Main()
{
var video = new MP4 { Title = "Eminem - Lose Yourself" };
var encoder = new MP4Encoder();
var mail = new MailService();
var message = new MessageService();
var log = new LogService();
// Đăng ký nhiều subscriber cho cùng một event
encoder.VideoEncoded += mail.OnVideoEncoded;
encoder.VideoEncoded += message.OnVideoEncoded;
encoder.VideoEncoded += log.OnVideoEncoded;
encoder.Encode(video);
Console.ReadKey();
}
}
Kết quả chạy
Đang encode video...
[MailService] Gửi email cho video: Eminem - Lose Yourself
[MessageService] Gửi tin nhắn cho video: Eminem - Lose Yourself
[LogService] Log: Video Eminem - Lose Yourself đã encode xong lúc 2024-01-15 10:30:45
Best Practices
- Luôn kiểm tra null trước khi invoke (dùng
?.Invoke từ C# 6).
- Sử dụng
EventHandler<TEventArgs> chuẩn thay vì delegate tùy chỉnh.
- Hủy đăng ký (
-=) khi không còn cần thiết để tránh memory leak.
- Đánh dấu method raise event là
protected virtual để cho phép override.