2009-02-21 30 views
22

Tôi cần sao chép người đăng ký của một sự kiện vào một sự kiện khác. Tôi có thể nhận được các thuê bao của một sự kiện (như MyEvent [0] trả lại một đại biểu)?Làm cách nào để có được người đăng ký sự kiện?

Nếu điều này là không thể, tôi sẽ sử dụng trình bổ sung thêm để thêm các đại biểu vào danh sách. Đó có phải là giải pháp tốt nhất?

Trả lời

20

C# sự kiện/đại biểu là đa phương tiện, do đó đại biểu là chính nó một danh sách. Từ bên trong lớp, để có được những người gọi cá nhân, bạn có thể sử dụng:

if(field != null) { // or the event-name for field-like events 
    // or your own event-type in place of EventHandler 
    foreach(EventHandler subscriber in field.GetInvocationList()) 
    { 
     // etc 
    } 
} 

Tuy nhiên, để gán tất cả cùng một lúc, chỉ cần sử dụng + = hoặc giao trực tiếp:

SomeType other = ... 
other.SomeEvent += localEvent; 
+0

Cảm ơn bạn đã chỉ ra điều đó. Đó là tốt nhất cho các sự kiện trong mã của riêng tôi. – weiqure

+0

Cảm ơn bạn rất nhiều vì điều này. Tôi cần một cách giải quyết tốt cho đối tượng nhân bản thông qua serialization nhị phân không được hưởng sự kiện đã đăng ký, hoặc người nào khác tôi đã phải thực hiện ICloneable trong vài trăm lớp. – user1039513

3

Cập nhật (cảm ơn người nhận xét): tính không thể ủy nhiệm có nghĩa là nhân bản không đạt được gì ngoài một bài tập.

Khi một viết:

myDelegate += AHandler 

một thể hiện ủy nhiệm hoàn toàn mới được tạo ra và gán cho myDelegate.

Do đó, mã bên dưới sẽ hoạt động giống hệt nhau mà không có cuộc gọi Clone.


MulticastDelegate (loại cơ bản) có phương pháp Clone.

Để có thể truy cập vào đại biểu cơ bản, bạn có thể cần phải tránh trình trợ giúp thông thường mà từ khóa sự kiện tạo và quản lý trực tiếp (tùy chỉnh thêm và xóa người truy cập).

Để hiển thị này:

 
    class Program { 
     public delegate void MyDelegate(string name); 

     public event MyDelegate EventOne; 

     public void HandlerOne(string name) { 
      Console.WriteLine("This is handler one: {0}", name); 
     } 
     public void HandlerTwo(string name) { 
      Console.WriteLine("This is handler two: {0}", name); 
     } 
     public void HandlerThree(string name) { 
      Console.WriteLine("This is handler three: {0}", name); 
     } 

     public void Run() { 
      EventOne += HandlerOne; 
      EventOne += HandlerTwo; 
      Console.WriteLine("Before clone"); 
      EventOne("EventOne"); 

      
            
 
  
             MyDelegate eventTwo = (MyDelegate)EventOne.Clone();
            
  
      MyDelegate eventTwo = EventOne; 
      Console.WriteLine("After 
            
 
  
             clone
            
 copy"); 
      EventOne("EventOne"); 
      eventTwo("eventTwo"); 

      Console.WriteLine("Change event one to show it is different"); 
      EventOne += HandlerThree; 
      EventOne("EventOne"); 
      eventTwo("eventTwo"); 
     } 

     static void Main(string[] args) { 
      (new Program()).Run(); 
     } 
    } 
+0

Bản thân là người không quan trọng tương đối - đại biểu không thay đổi, vì vậy bạn chỉ có thể sao chép tham chiếu đại biểu. –

+0

Trừ khi, như trong mẫu, bạn muốn sửa đổi bản gốc hoặc sao chép độc lập. – Richard

+0

Richard - không, điều đó sẽ hoạt động ** giống hệt ** mà không có bước Clone(). –

13

Nếu sự kiện là một trong những xuất bản bởi lớp khác, bạn không thể - ít nhất, không đáng tin cậy. Trong khi chúng ta thường nghĩ về một sự kiện như là một biến đại biểu, nó thực sự chỉ là một cặp phương thức: thêm và loại bỏ (hoặc đăng ký và hủy đăng ký).

Nếu đó là mã của riêng bạn đang xuất bản sự kiện, thật dễ dàng - bạn có thể làm cho việc thêm/xóa người truy cập làm bất cứ điều gì bạn thích.

Hãy xem my article on events và xem điều đó có giúp ích cho bạn hay không. Nếu không, vui lòng cung cấp thêm chi tiết về những gì bạn muốn làm, chỉ định bit nào bạn có thể sửa đổi và bạn không thể sửa đổi mã nào.

1

Trong trường hợp bạn cần phải kiểm tra người đăng ký sự kiện của lớp học bên ngoài ':

EventHandler e = typeof(ExternalClass) 
    .GetField(nameof(ExternalClass.Event), BindingFlags.Instance | BindingFlags.NonPublic) 
    .GetValue(instanceOfExternalClass) as EventHandler; 
if (e != null) 
{ 
    Delegate[] subscribers = e.GetInvocationList(); 
} 
Các vấn đề liên quan