Cách thêm đại biểu vào giao diện C #


91

Tôi cần có một số đại biểu trong lớp của tôi.

Tôi muốn sử dụng giao diện để "nhắc nhở" tôi đặt các đại diện này.

Làm thế nào để?

Lớp của tôi trông như thế này:

public class ClsPictures : myInterface
{
    // Implementing the IProcess interface
    public event UpdateStatusEventHandler UpdateStatusText;
    public delegate void UpdateStatusEventHandler(string Status);

    public event StartedEventHandler Started;
    public delegate void StartedEventHandler();
}

Tôi cần một giao diện để buộc các đại biểu đó:

public interface myInterface
{
   // ?????
}

Câu trả lời:


142

Đó là khai báo các kiểu đại biểu . Chúng không thuộc về một giao diện. Mặc dù vậy, các sự kiện sử dụng các kiểu đại biểu đó vẫn tốt trong giao diện:

public delegate void UpdateStatusEventHandler(string status);
public delegate void StartedEventHandler();

public interface IMyInterface
{       
    event UpdateStatusEventHandler StatusUpdated;    
    event StartedEventHandler Started;
}

Việc triển khai sẽ không (và không nên) khai báo lại kiểu đại biểu, bất kỳ quá trình triển khai nào sẽ khai báo lại bất kỳ kiểu nào khác được sử dụng trong giao diện.


Điều này không phù hợp với tôi. Tôi khẳng định rằng tôi đã làm mọi thứ theo cách này, tuy nhiên, trình xử lý trong giao diện của tôi không được công nhận. Lớp triển khai giao diện của tôi đang phàn nàn rằng lớp không khớp với kiểu trả về giao diện của System.EventHandler.
Chucky,

1
@Chucky: Có vẻ như bạn nên đặt một câu hỏi mới với một ví dụ ngắn gọn nhưng đầy đủ để giải thích vấn đề. Câu trả lời tôi đã đưa cho thực sự làm việc.
Jon Skeet,

4
Tôi không nhận ra rằng các đại biểu có cùng mức khả năng truy cập như các lớp. Tôi luôn nghĩ rằng chúng cần được gói gọn trong một lớp.
Purusartha

7
@Purusartha: Đó không phải là khả năng tiếp cận - đó chỉ là vấn đề của các đại biểu là các loại (lớp học, trên thực tế) cũng giống như giao diện vv
Jon Skeet

29

Kể từ .NET 3.5, bạn cũng có thể sử dụng đại biểu System.Action mà không cần khai báo kiểu của riêng bạn.

Điều này sẽ dẫn đến giao diện sau:

public interface myInterface
{       
   // Implementing the IProcess interface
   event Action<String> UpdateStatusText;

   event Action Started;
}

+1. Tôi thấy Hành động / Chức năng thanh lịch hơn nhiều (và dễ đọc) hơn so với các kiểu đại biểu truyền thống bạn có thể xác định chúng trong giao diện của mình.
chrnola

2
Câu trả lời này không giải quyết câu hỏi (cách triển khai myInterface).
lharper71

10

Chỉ cần hiển thị đại biểu dưới dạng thuộc tính

public delegate void UpdateStatusEventHandler(string status);
public delegate void StartedEventHandler();

public interface IMyInterface
{       
    UpdateStatusEventHandler StatusUpdated {get; set;}    
    StartedEventHandler Started {get; set;}
}

7

Câu trả lời của Jon Skeet là đúng, tôi chỉ muốn thêm một ghi chú.

Các giao diện không ở đó để "nhắc nhở" bạn phải làm gì hoặc những gì cần đưa vào các lớp học của bạn. Giao diện là phương tiện trừu tượng, được sử dụng trong các phương pháp thiết kế và lập trình hướng đối tượng. Có thể bạn không cần khai báo giao diện, trừ khi bạn muốn xem một số cá thể lớp cụ thể làm giao diện ở nơi khác trong chương trình của bạn (Trừu tượng).

Nếu bạn muốn thực thi một số tiêu chuẩn mã hóa trong dự án của mình, bạn có thể muốn thử sử dụng các công cụ phân tích mã (như trong Visual Studio) - Chúng cho phép các phần mở rộng mà bạn có thể kết hợp để thêm các quy tắc phân tích mã của riêng bạn.

Sử dụng phân tích mã, nếu bạn "quên" thêm các đại diện (mặc dù tôi không thấy điểm của việc quên nó, như thể đại biểu không được sử dụng, nó không cần thiết) bạn sẽ nhận được cảnh báo / lỗi.


1
Bạn có thể đúng, nhưng đôi khi bạn đưa ra một số giả định rằng ngay cả với tài liệu tốt cũng khó nhớ sau một thời gian. Tôi cố gắng để tái sử dụng mã của tôi nhưng đôi khi tôi không thể nhớ những gì nó cốt lõi và những gì nó không (khi nói đến các đại biểu - thật khó cho tôi để xem hình ảnh lớn ...)
Asaf

1

Một trong các nhận xét của bạn đã tham chiếu đến kiểu trả về của trình xử lý sự kiện. Bạn quan tâm hơn đến loại trình xử lý hay dữ liệu quay lại từ sự kiện? Nếu đó là thứ sau, thì điều này có thể hữu ích. Nếu không, thì giải pháp này sẽ không đủ, nhưng có thể giúp bạn đến gần hơn với những gì bạn đang tìm kiếm.

Tất cả những gì bạn phải làm là khai báo trình xử lý sự kiện của bạn là trình xử lý sự kiện chung trong cả giao diện và triển khai của bạn và bạn có thể tùy chỉnh kết quả trả về.

Lớp conrete của bạn sẽ trông như thế này:

public class ClsPictures : myInterface
{
    // Implementing the IProcess interface
    public event EventHandler<UpdateStatusEventArgs> UpdateStatusText;
    //no need for this anymore: public delegate void UpdateStatusEventHandler(string Status);

    public event EventHandler<StartedEventArgs> Started;
    //no need for this anymore: public delegate void StartedEventHandler();
}

Giao diện của bạn sẽ như thế này:

public interface myInterface
{
   event EventHandler<StartedEventArgs> Started;
   event EventHandler<UpdateStatusEventArgs> UpdateStatusText;
}

Bây giờ các args sự kiện đang trả về các loại của bạn, bạn có thể kết nối chúng trong bất kỳ trình xử lý nào mà bạn xác định.

Để tham khảo: https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx


0

Giao diện kế thừa bên trong lớp dẫn xuất của bạn sẽ nhắc bạn xác định và liên kết những thứ bạn đã khai báo trong đó.

Nhưng bạn cũng có thể muốn sử dụng nó một cách rõ ràng và bạn vẫn cần phải liên kết nó với một đối tượng.

Ví dụ: sử dụng mẫu Đảo ngược điều khiển:

class Form1 : Form, IForm {
   public Form1() {
     Controls.Add(new Foo(this));
   }

   // Required to be defined here.
   void IForm.Button_OnClick(object sender, EventArgs e) {
     ...
     // Cast qualifier expression to 'IForm' assuming you added a property for StatusBar.
     //((IForm) this).StatusBar.Text = $"Button clicked: ({e.RowIndex}, {e.SubItem}, {e.Model})";
   }
 }

Bạn có thể thử một cái gì đó như thế này.

interface IForm {
  void Button_OnClick(object sender, EventArgs e);
}


class Foo : UserControl {
  private Button btn = new Button();

  public Foo(IForm ctx) {
     btn.Name = "MyButton";
     btn.ButtonClick += ctx.Button_OnClick;
     Controls.Add(btn);
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.