• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

[Net] *** Sử dụng Delegate trong VB.Net và C#

Các bài viết hướng dẫn về Visual Basic .NET và C#

Điều hành viên: tungcan5diop, QUANITGROBEST

Hình đại diện của người dùng
anhtuyenbk
Guru
Guru
Bài viết: 1311
Ngày tham gia: T.Năm 22/09/2005 4:12 pm
Đến từ: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 time

[Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi anhtuyenbk » T.Sáu 04/07/2008 10:24 pm

Tên bài viết: Sử dụng Delegate trong VB.Net và C#
Tác giả: Nguyễn Anh Tuyên
Cấp độ bài viết: Advance
Tóm tắt: Sử dụng Delegate trong VB.Net và C#



Sử dụng Delegate trong VB.Net và C#


1. Delegate đại diện cho một Method

Delegate cho chúng ta một cách thuận tiện hơn để thao tác với các method (bao gồm cả hàm và thủ tục).
Delegate cho phép chúng ta truyền một method như một tham số vào một Method khác ( hay nói cách khác là delegate đại diện cho một method).
Ví dụ: Ta tạo ra một delegate mô tả một method gồm có 2 tham số kiểu object với giá trị trả về là kiểu boolean.

Mã: Chọn hết

  1. Public Delegate Function CompareOp(ByVal object1 As Object, ByVal object2 As Object) As Boolean

Mã: Chọn hết

  1. public delegate bool CompareOp(object object1, object object2);

Bây giờ ta tạo ra các method có chữ ký giống với delegate trên (nghĩa là nó có cùng số lượng tham số (cùng kiểu tham số) và cùng như kiểu trả về).
Các method sau kiểm tra 2 con số là tăng dần hay giảm dần. Ta thấy rằng các Method sau có chữ ký giống với chữ ký của Delegate.

Mã: Chọn hết

  1. Public Shared Function Sotangdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
  2.         If Convert.ToInt32(object1) < Convert.ToInt32(object2) Then
  3.             Return True
  4.         Else
  5.             Return False
  6.         End If
  7.  
  8.     End Function
  9.     Public Shared Function Sogiamdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
  10.         Return Not Sotangdan(object1, object2)
  11.     End Function

--------------------

Mã: Chọn hết

  1. public static bool Sotangdan(object object1, object object2)
  2.     {
  3.         if (Convert.ToInt32(object1) < Convert.ToInt32(object2))
  4.         {
  5.             return true;
  6.         }
  7.         else
  8.         {
  9.             return false;
  10.         }
  11.  
  12.     }
  13.     public static bool Sogiamdan(object object1, object object2)
  14.     {
  15.         return !Sotangdan(object1, object2);
  16.     }

Method sau là Method BubbleSort nhận tham số đầu vào là một mảng và một method có kiểu giống Delegate CompareOP. Nó có nhiệm vụ sắp xếp mảng được truyền vào.

Mã: Chọn hết

  1. Public Shared Sub BubbleSort(ByRef Mang() As Object, ByVal compare As CompareOP)
  2.         Dim temp As Object
  3.         For i As Integer = 0 To Mang.Length - 2
  4.             For j As Integer = i + 1 To Mang.Length - 1
  5.                 If compare(Mang(i), Mang(j)) = False Then
  6.                     temp = Mang(i)
  7.                     Mang(i) = Mang(j)
  8.                     Mang(j) = temp
  9.                 End If
  10.             Next
  11.  
  12.         Next
  13.     End Sub

Mã: Chọn hết

  1. public static void BubbleSort(ref object[] Mang, CompareOP compare)
  2.     {
  3.         object temp;
  4.         for (int i = 0; i <= Mang.Length - 2; i++) {
  5.             for (int j = i + 1; j <= Mang.Length - 1; j++) {
  6.                 if (compare(Mang(i), Mang(j)) == false)
  7.                 {
  8.                     temp = Mang(i);
  9.                     Mang(i) = Mang(j);
  10.                     Mang(j) = temp;
  11.                 }
  12.             }
  13.  
  14.         }
  15.     }

Bây giờ ta tạo ra một Class SortClass hoàn chỉnh có nhiệm vụ sắp xếp một mảng số cho trước theo kiểu tăng dần và giảm dần ứng dụng các Method mới vừa làm ở trên.

Mã: Chọn hết

  1. Public Class SortClass
  2.  
  3.     Public Delegate Function CompareOp(ByVal object1 As Object, ByVal object2 As Object) As Boolean
  4.     Public Shared Function Sotangdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
  5.         If Convert.ToInt32(object1) < Convert.ToInt32(object2) Then
  6.             Return True
  7.         Else
  8.             Return False
  9.         End If
  10.  
  11.     End Function
  12.     Public Shared Function Sogiamdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
  13.         Return Not Sotangdan(object1, object2)
  14.     End Function
  15.  
  16.  
  17.     Public Shared Sub BubbleSort(ByRef Mang() As Object, ByVal compare As CompareOP)
  18.         Dim temp As Object
  19.         For i As Integer = 0 To Mang.Length - 2
  20.             For j As Integer = i + 1 To Mang.Length - 1
  21.                 If compare(Mang(i), Mang(j)) = False Then
  22.                     temp = Mang(i)
  23.                     Mang(i) = Mang(j)
  24.                     Mang(j) = temp
  25.                 End If
  26.             Next
  27.  
  28.         Next
  29.     End Sub
  30. End Class

-------------------

Mã: Chọn hết

  1. public class SortClass
  2. {
  3.  
  4.     public delegate bool CompareOp(object object1, object object2);
  5.     public static bool Sotangdan(object object1, object object2)
  6.     {
  7.         if (Convert.ToInt32(object1) < Convert.ToInt32(object2))
  8.         {
  9.             return true;
  10.         }
  11.         else
  12.         {
  13.             return false;
  14.         }
  15.  
  16.     }
  17.     public static bool Sogiamdan(object object1, object object2)
  18.     {
  19.         return !Sotangdan(object1, object2);
  20.     }
  21.  
  22.  
  23.     public static void BubbleSort(ref object[] Mang, CompareOP compare)
  24.     {
  25.         object temp;
  26.         for (int i = 0; i <= Mang.Length - 2; i++) {
  27.             for (int j = i + 1; j <= Mang.Length - 1; j++) {
  28.                 if (compare(Mang(i), Mang(j)) == false)
  29.                 {
  30.                     temp = Mang(i);
  31.                     Mang(i) = Mang(j);
  32.                     Mang(j) = temp;
  33.                 }
  34.             }
  35.  
  36.         }
  37.     }
  38. }
  39.  


Cách sử dụng như sau:

Mã: Chọn hết

  1. Private Sub btnSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSort.Click
  2.         Dim Number() As Object = {2, 1, 7, 9, 11}
  3.         SortClass.BubbleSort(Number, AddressOf SortClass.Sotangdan)
  4.         SortClass.BubbleSort(Number, AddressOf SortClass.Sogiamdan)        
  5.     End Sub


Mã: Chọn hết

  1. private void btnSort_Click(object sender, System.EventArgs e)
  2.     {
  3.         object[] Number = {2, 1, 7, 9, 11};
  4.         SortClass.BubbleSort(Number, SortClass.Sotangdan);
  5.         SortClass.BubbleSort(Number, SortClass.Sogiamdan);
  6.     }
Sửa lần cuối bởi anhtuyenbk vào ngày T.Bảy 05/07/2008 3:47 pm với 3 lần sửa.


Kiếm cơm cho qua ngày tháng
https://www.facebook.com/pinduphongpisenchinhhang

Hình đại diện của người dùng
clarkkent
Mạnh Thường Quân
Mạnh Thường Quân
Bài viết: 1641
Ngày tham gia: T.Tư 16/04/2008 11:25 am
Đến từ: Chợ Lách - Bến Tre
Been thanked: 31 time
Liên hệ:

Re: Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi clarkkent » T.Sáu 04/07/2008 10:29 pm

Hay ! Hiểu được đấy :D =D> =D> =D>
• Hôm bây: www.tinsoftware.com ^ ^
Cố gắng lên...

neverland87
Guru
Guru
Bài viết: 490
Ngày tham gia: T.Bảy 26/05/2007 4:31 pm
Been thanked: 8 time

Re: Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi neverland87 » T.Sáu 04/07/2008 10:43 pm

Làm thêm cái event luôn đi bác Tuyền. :x
SIMPLY THE BEST - ĐƠN GIẢN LÀ TỐT NHẤT

Hình đại diện của người dùng
anhtuyenbk
Guru
Guru
Bài viết: 1311
Ngày tham gia: T.Năm 22/09/2005 4:12 pm
Đến từ: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 time

Re: Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi anhtuyenbk » T.Bảy 05/07/2008 3:43 pm

2. Delegate và Event
Delegate ngoài việc dùng cho mục đích ở trên, nó còn dùng cho nhiều mục đích khác ví dụ sử dụng Delegate để xử lý Event, phần này ta sẽ thảo luận về nó.
Đề bài : Ta tạo một class DanhsachXe quản lý các Xemay mà ta đã mua được
2.1 Đầu tiên ta tạo ra một class mô tả các phần tử xe máy gồm tên xe và phân khối của xe

Mã: Chọn hết

  1. Public Class XeMay
  2.         Public Tenxe As String
  3.         Public Phankhoi As String
  4.         Public Sub New(ByVal pTenxe As String, ByVal pPhankhoi As String)
  5.             Me.Tenxe = pTenxe
  6.             Me.Phankhoi = pPhankhoi
  7.         End Sub
  8.     End Class

hay

Mã: Chọn hết

  1. public class XeMay
  2.     {
  3.         public string Tenxe;
  4.         public string Phankhoi;
  5.         public XeMay(string pTenxe, string pPhankhoi )
  6.         {
  7.             this.Tenxe = pTenxe;
  8.             this.Phankhoi = pPhankhoi;
  9.         }
  10.     }


2.2 Ta tạo ra một Delegate để xứ lý Event khi mua thêm một xe mới, gồm 2 tham số là đối tượng tạo ra Event và một tham số mô tả xe máy được mua thêm

Mã: Chọn hết

  1. Public Delegate Sub XemayHandler(ByVal sender As Object, ByVal e As XeMay)

hay

Mã: Chọn hết

  1. public delegate void XemayHandler(object sender, XeMay e);


2.3 Xây dựng class Quản lý xe máy

Mã: Chọn hết

  1. Public Delegate Sub XemayHandler(ByVal sender As Object, ByVal e As XeMay)
  2.     Public Class DanhsachXe
  3.         Public Event AddNewXe As XemayHandler
  4.  
  5.         Private Items As New List(Of XeMay)()
  6.         Public Sub Add(ByVal item As XeMay)
  7.             Items.Add(item)
  8.             RaiseEvent  AddNewXe(Me, item)
  9.         End Sub
  10.     End Class

hay

Mã: Chọn hết

  1. public class DanhsachXe
  2.     {
  3.         public event XemayHandler AddNewXe;
  4.        
  5.         List<XeMay> Items = new List<XeMay>();
  6.         public void Add(XeMay item)
  7.         {
  8.             Items.Add(item);
  9.             AddNewXe(this, item);
  10.         }
  11.     }

Các bạn có để ý thấy rằng trong class trên chứa đoạn khai báo event mà sẽ được sinh ra khi ta mua thêm một chiếc xe máy bằng cách sử dụng Method Add

Mã: Chọn hết

  1. Public Event AddNewXe As XemayHandler

Hay

Mã: Chọn hết

  1.        public event XemayHandler AddNewXe;

Đoạn khai báo này nghĩ là Event AddNewXe sẽ được xử lý bởi Delegate XemayHandler
Khi ta dùng method Add thì Event sẽ được sinh ra bằng method sau
Vb.Net

Mã: Chọn hết

  1.             RaiseEvent  AddNewXe(Me, item)

Hay C#

Mã: Chọn hết

  1.            AddNewXe(this, item);
  2.  


2.4 Cách sử dụng
VB.Net

Mã: Chọn hết

  1. Public DS As DanhsachXe
  2.         ' Khai báo bi?n qu?n lý xe
  3.         Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
  4.             DS = New DanhsachXe()
  5.             AddHandler DS.AddNewXe, AddressOf DS_AddNewXe
  6.             'X? lý Event mua xe m?i
  7.         End Sub
  8.  
  9.         'Ðo?n code x? lý Event Mua xe m?i
  10.         Private Sub DS_AddNewXe(ByVal sender As Object, ByVal e As XeMay)
  11.             MessageBox.Show("Tao m?i mua thêm xe " & e.Tenxe & " mày th?y ko??")
  12.         End Sub
  13.         'Add thêm xe m?i vào danh sách
  14.         Private Sub button2_Click(ByVal sender As Object, ByVal e As EventArgs)
  15.             DS.Add(New XeMay("Air Blade", "110cc"))
  16.         End Sub
  17.  
C#

Mã: Chọn hết

  1. public DanhsachXe DS; // Khai báo biến quản lý xe
  2.  
  3.         private void Form1_Load(object sender, EventArgs e)
  4.         {          
  5.             DS = new DanhsachXe();
  6.             //Xử lý Event mua xe mới
  7.             DS.AddNewXe += new XemayHandler(DS_AddNewXe);
  8.         }
  9.          
  10.         //Đoạn code xủ lý Event Mua xe mới
  11.         void DS_AddNewXe(object sender, XeMay e)
  12.         {
  13.             MessageBox.Show("Tao mới mua thêm xe " + e.Tenxe + " mày thấy ko??");
  14.         }
  15.         //Add thêm xe mới vào danh sách
  16.         private void button2_Click(object sender, EventArgs e)
  17.         {
  18.             DS.Add(new XeMay("Air Blade", "110cc"));
  19.            
  20.         }
  21.  
Kiếm cơm cho qua ngày tháng
https://www.facebook.com/pinduphongpisenchinhhang

Hình đại diện của người dùng
manhhung87
Thành viên tâm huyết
Thành viên tâm huyết
Bài viết: 320
Ngày tham gia: T.Sáu 30/05/2008 8:47 am
Đến từ: Ha Noi University of Industry
Been thanked: 1 time
Liên hệ:

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi manhhung87 » T.Tư 30/07/2008 6:51 am

Cám ơn nhé, cái này quả là tuyệt vời. Bạn có tài liệu nào giới thiệu về cách sử dụng chương trình Visual studio 2005 không, cái này sử dụng khó quá ( Tiếng việt là tốt nhất).
Công cụ quản trị website.
http://www.vnkweb.com

dllcoder
Bài viết: 9
Ngày tham gia: T.Hai 20/10/2008 10:39 pm

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi dllcoder » T.Hai 20/10/2008 11:51 pm

Bài viết rất hay và dễ hiểu, thanks anhtuyenbk :)

thanh.bob
Bài viết: 9
Ngày tham gia: CN 07/12/2008 3:32 pm

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi thanh.bob » T.Tư 31/12/2008 11:50 am

Bài viết hay thật, cám ơn anh TuyenBK nhé :x , thật sự là cái delegate này em chưa biết j :-? , bây giờ đã hiểu rõ hơn rùi =D> =D>

huynguyen
Thành viên chính thức
Thành viên chính thức
Bài viết: 16
Ngày tham gia: T.Hai 31/03/2008 9:32 pm

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi huynguyen » T.Tư 18/03/2009 9:04 pm

Đúng là bài viết hướng dẫn chi tiết
Nhưng điều quan trọng nhất là bạn chưa nói mục đích dùng delegate để làm gì ^_^

Hình đại diện của người dùng
tungcan5diop
Cựu chiến binh
Cựu chiến binh
Bài viết: 1123
Ngày tham gia: T.Tư 24/09/2008 4:04 pm
Đến từ: TPHCM
Has thanked: 1 time
Been thanked: 28 time

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi tungcan5diop » T.Tư 18/03/2009 10:17 pm

huynguyen đã viết:Đúng là bài viết hướng dẫn chi tiết
Nhưng điều quan trọng nhất là bạn chưa nói mục đích dùng delegate để làm gì ^_^

dùng Delegate để truyền dữ liệu giữa 2 form,giữa các Class với nhau,bạn đã từng trong một hàm mà mình gọi một hảm khác theo Address của nó chưa? :D
Hỡi thế gian bug(lỗi) là gì?
Mà sửa...hoài không hết!

huynguyen
Thành viên chính thức
Thành viên chính thức
Bài viết: 16
Ngày tham gia: T.Hai 31/03/2008 9:32 pm

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi huynguyen » T.Bảy 21/03/2009 4:59 pm

Việc đó quá bình thường, chưa phải mục đích chính của delegate.
Mục đích chính của delegate chính là giúp xử lý bất đồng bộ tạo cho người dùng cảm giác chương trình chạy rất nhanh.
Đó mới là điều đáng cần để sử dụng delegate, sử dụng delegate chỉ để truyền dữ liệu thì chẳng khác gì dùng dao mổ trâu giết gà.

Hình đại diện của người dùng
tungcan5diop
Cựu chiến binh
Cựu chiến binh
Bài viết: 1123
Ngày tham gia: T.Tư 24/09/2008 4:04 pm
Đến từ: TPHCM
Has thanked: 1 time
Been thanked: 28 time

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi tungcan5diop » T.Bảy 21/03/2009 10:05 pm

huynguyen đã viết:Việc đó quá bình thường, chưa phải mục đích chính của delegate.
Mục đích chính của delegate chính là giúp xử lý bất đồng bộ tạo cho người dùng cảm giác chương trình chạy rất nhanh.
Đó mới là điều đáng cần để sử dụng delegate, sử dụng delegate chỉ để truyền dữ liệu thì chẳng khác gì dùng dao mổ trâu giết gà.

bạnb biết rành vậy sao còn hỏi..hỏi mà giống như đố vậy.. :D
Hỡi thế gian bug(lỗi) là gì?
Mà sửa...hoài không hết!

Hình đại diện của người dùng
anhtuyenbk
Guru
Guru
Bài viết: 1311
Ngày tham gia: T.Năm 22/09/2005 4:12 pm
Đến từ: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 time

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi anhtuyenbk » T.Bảy 21/03/2009 11:09 pm

huynguyen đã viết:Đúng là bài viết hướng dẫn chi tiết
Nhưng điều quan trọng nhất là bạn chưa nói mục đích dùng delegate để làm gì ^_^

Đây là 1 bài viết hướng dẫn, nếu bạn thấy còn thiếu thì có thể bổ sung thêm. :D :D
Kiếm cơm cho qua ngày tháng
https://www.facebook.com/pinduphongpisenchinhhang

huynguyen
Thành viên chính thức
Thành viên chính thức
Bài viết: 16
Ngày tham gia: T.Hai 31/03/2008 9:32 pm

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi huynguyen » CN 22/03/2009 9:53 pm

Trong bài viết của mình ko có dấu ?
Mình ko có ý hỏi mà ý là mong đợi tác giả viết thêm 1 phần rất quan trọng của delegate.
Sorry nếu có nói quá lời nhưng mình nghĩ nghiên cứu công nghệ hay kỹ thuật ko phải chỉ dừng lại ở mức là dùng nó như thế, nó định nghĩa ra sao. Như vậy thì quá chính quy và hàn lâm. Chúng ta nên suy nghĩ đến việc nghiên cứu công nghệ và kỹ thuật ấy mục đích chính dùng để làm gì, ứng dụng vào điều gì, như vậy nó sẽ thực tế và bài viết sẽ có ý nghĩa hơn, từ đó sẽ làm cho mọi người sáng tạo bổ sung thêm.
Hiện tại bài viết của bạn hoàn chỉnh rồi, ko còn điều gì cần bổ sung, tuy nhiên nó quá hàn lâm.

Hình đại diện của người dùng
anhtuyenbk
Guru
Guru
Bài viết: 1311
Ngày tham gia: T.Năm 22/09/2005 4:12 pm
Đến từ: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 time

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi anhtuyenbk » CN 22/03/2009 10:15 pm

Như mình đã nói ở trên, nếu bài viết có điểm gì còn thiếu sót hay chưa vừa ý bạn thì bạn cứ việc bổ sung thêm cho nó hoàn chính hơn.
Nếu bạn cảm thấy nó quá hàn lâm, chưa có ý nghĩa thực tế nhiều và bạn thực sự có lòng nhiệt tình muốn đóng góp, vậy thì tại sao bạn ko trực tiếp viết để mọi người học hỏi thêm, thay vì đợi chính tác giả viết.
từ đó sẽ làm cho mọi người sáng tạo bổ sung thêm.

Nếu một người thực sự muốn đóng góp, muốn chia sẻ với mọi người, họ sẽ đóng góp thôi, chứ ko cần động lực thúc đẩy gì cả.
Kiếm cơm cho qua ngày tháng
https://www.facebook.com/pinduphongpisenchinhhang

Hình đại diện của người dùng
Kỳ Nam
Guru
Guru
Bài viết: 510
Ngày tham gia: CN 12/08/2007 8:47 pm
Đến từ: Qui Nhơn
Been thanked: 1 time
Liên hệ:

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi Kỳ Nam » CN 22/03/2009 10:19 pm

huynguyen đã viết:Việc đó quá bình thường, chưa phải mục đích chính của delegate.
Mục đích chính của delegate chính là giúp xử lý bất đồng bộ tạo cho người dùng cảm giác chương trình chạy rất nhanh.
Đó mới là điều đáng cần để sử dụng delegate, sử dụng delegate chỉ để truyền dữ liệu thì chẳng khác gì dùng dao mổ trâu giết gà.

A delegate is a form of object-oriented function pointer that allows a function to be invoked indirectly by way of a reference to the function.

đó mới là mục đích ra đời của delegate , mấy cái kia chỉ là những gì có thể làm được bằng cách dùng delegate

delegate , thực ra là class inherit từ class System.Delegate , class đó được tạo khi dùng câu lệnh khai báo delegate , khi compile sẽ tự động được compiler thêm dô các method begininvoke / endinvoke giúp chạy 0 đồng bộ , các method đó có được là nhờ các class trong namespace system.threading

-> nếu kêu Mục đích chính của delegate chính là giúp xử lý bất đồng bộ là hơi bị wái ; 0 cần delegate vẫn có thể làm mấy chiện mà huynguyen coi là Mục đích chính của delegate

ltvvt
Thành viên chính thức
Thành viên chính thức
Bài viết: 19
Ngày tham gia: T.Hai 01/11/2010 8:25 am

Re: [Net] *** Sử dụng Delegate trong VB.Net và C#

Gửi bàigửi bởi ltvvt » T.Hai 15/11/2010 9:34 pm

anh ơi làm vậy nó xuất ra dãy số ấy ở mô vậy anh?? em vẫn không hiểu??


Quay về “[.NET] Bài viết hướng dẫn”

Đang trực tuyến

Đang xem chuyên mục này: Không có thành viên nào trực tuyến.2 khách