인터페이스 C #에 대리자를 추가하는 방법


91

수업에 델리게이트가 필요합니다.

인터페이스를 사용하여 이러한 델리게이트를 설정하도록 "알리게"하고 싶습니다.

어떻게?

내 수업은 다음과 같습니다.

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();
}

해당 대리자를 강제하는 인터페이스가 필요합니다.

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

답변:


142

그것들은 대리자 유형을 선언하고 있습니다 . 그들은 인터페이스에 속하지 않습니다. 이러한 대리자 유형을 사용 하는 이벤트 는 다음과 같이 인터페이스에있는 것이 좋습니다.

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

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

구현은 인터페이스에서 사용되는 다른 유형을 재 선언하는 것보다 더 많이 델리게이트 유형을 재 선언하지 않습니다 (그리고 그렇게해서는 안됩니다).


이것은 나를 위해 작동하지 않습니다. 이 방법으로 모든 작업을 수행했지만 인터페이스 내의 핸들러가 인식되지 않는다고 확신합니다. 인터페이스를 구현하는 내 클래스는 클래스가 System.EventHandler의 인터페이스 반환 유형과 일치하지 않는다고 불평합니다.
Chucky

1
@Chucky : 문제를 설명하는 짧지 만 완전한 예제로 새로운 질문을해야하는 것 같습니다. 내가 준 대답은 실제로 효과 있습니다.
Jon Skeet 2013

4
대리자가 수업과 같은 수준의 접근성을 가지고 있다는 사실을 몰랐습니다. 나는 항상 그것들이 클래스 내에 캡슐화되어야한다고 생각했습니다.
Purusartha 2014 년

7
@Purusartha : - 대의원 유형 인의 문제 (클래스 사실) 그냥만큼 인터페이스 등 그 접근성이 아니다
존 소총

29

.NET 3.5부터는 고유 한 유형을 선언 할 필요없이 System.Action 대리자를 사용할 수도 있습니다.

결과적으로 다음과 같은 인터페이스가 생성됩니다.

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

   event Action Started;
}

+1. 나는 액션 / Func을 기존 위임 유형보다 훨씬 더 우아 (읽을)로 발견 하고 당신은 당신의 인터페이스를 정의 할 수 있습니다.
chrnola

2
이 답변은 질문 (myInterface 구현 방법)을 다루지 않습니다.
lharper71

10

대리자를 속성으로 노출하기 만하면됩니다.

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

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

7

Jon Skeet의 대답이 맞습니다. 메모를 추가하고 싶습니다.

수행 할 작업 또는 클래스에 포함 할 항목을 "알려주는"인터페이스가 없습니다. 인터페이스는 객체 지향 프로그래밍 및 디자인 방법에 사용되는 추상화 수단입니다. 프로그램의 다른 곳에서 인터페이스로 구체적인 클래스 인스턴스를보고 싶지 않다면 (추상화) 인터페이스 선언이 전혀 필요하지 않을 수도 있습니다.

프로젝트에서 일부 코딩 표준을 적용하려는 경우 코드 분석 도구 (예 : Visual Studio)를 사용해 볼 수 있습니다. 확장을 허용하여 사용자 고유의 코드 분석 규칙을 추가 할 수 있습니다.

코드 분석을 사용하여 대리자를 추가하는 것을 "잊으면"(대리자가 사용되지 않는 것처럼 잊어 버리는 지점은 알 수 없지만 필요하지 않음) 경고 / 오류가 발생합니다.


1
당신이 옳을 수도 있지만, 좋은 문서화로도 잠시 후에 기억하기 어렵다는 가정을 할 때가 있습니다. 내 코드를 재사용하려고하지만 때로는 핵심이 무엇인지 기억하지 못합니다 (대리인의 경우 큰 그림을보기가 어렵습니다 ...)
Asaf

1

귀하의 의견 중 하나가 이벤트 핸들러의 반환 유형을 참조했습니다. 핸들러의 유형이나 이벤트에서 돌아 오는 데이터에 더 관심이 있습니까? 후자의 경우 도움이 될 수 있습니다. 그렇지 않은 경우이 솔루션으로는 충분하지 않지만 원하는 항목에 더 가까이 다가가는 데 도움이 될 수 있습니다.

인터페이스와 구현 모두에서 이벤트 핸들러를 일반 이벤트 핸들러로 선언하기 만하면 반환 결과를 사용자 정의 할 수 있습니다.

conrete 클래스는 다음과 같습니다.

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();
}

인터페이스는 다음과 같습니다.

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

이제 이벤트 인수가 유형을 반환하므로 정의한 모든 핸들러에 연결할 수 있습니다.

참고 : https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx


0

파생 클래스 내에서 상속 된 인터페이스는 선언 한 내용을 정의하고 연결하도록 알려줍니다.

그러나 명시 적으로 사용하고 싶을 수도 있으며 여전히 개체에 연결해야합니다.

예를 들어 Inversion of Control 패턴을 사용하는 경우 :

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})";
   }
 }

이런 식으로 시도해 볼 수 있습니다.

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);
  }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.