2010-10-16 28 views
67

我需要在我的班级中有一些代表。如何将代理添加到接口C#

我想使用界面来“提醒”我设置这些代表。

如何?

我的班级是这样的:

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 
{ 
    // ????? 
} 

回答

115

那些正在申报委托类型。它们不属于界面。使用这些委托类型的事件的罚款是在界面虽然:

public delegate void UpdateStatusEventHandler(string status); public delegate void StartedEventHandler(); public interface IMyInterface { event UpdateStatusEventHandler StatusUpdated; event StartedEventHandler Started; } 

实施,将不会(也不应该)重新声明委托类型,使用

任何比它会重新声明任何其他类型在一个界面中。

+0

这恰恰是不适合我的工作。我很积极,我已经这样做了所有事情,然而,我的界面中的处理程序没有得到认可。我的类实现接口是抱怨该类不匹配System.EventHandler的接口返回类型。 – Chucky 2013-07-16 10:53:20

+1

@Chucky:听起来你应该用一个简短但完整的例子来解答这个问题。我给出的答案确实*起作用。 – 2013-07-16 10:58:28

+4

我没有意识到代表具有与班级一样的可访问性。我一直认为他们需要被封装在一个班级中。 – Purusartha 2014-10-13 05:54:40

6

乔恩Skeet的答案是正确的,我只是想添加一个笔记。

接口不是为了“提醒”你要做什么,或者在你的课程中包含什么。接口是抽象的手段,用于面向对象的编程和设计方法。也许你根本不需要接口声明,除非你想在程序的其他地方看到一些具体的类实例作为接口(Abstraction)。

如果要强制在你的项目中一些编码标准,您可能希望使用代码分析工具来尝试(如在Visual Studio) - 他们允许扩展,你可以将添加你自己的代码分析规则。

使用代码分析,如果您“忘记”添加代表(虽然我没有看到忘记它的地步,好像代理没有被使用,但不需要),您将得到一个警告/错误。

+1

你可能是对的,但是有时候你做出一些假设,即使有良好的文档一段时间后很难记住。我尝试重复使用我的代码,但有时我不记得它是什么核心,什么不是(当涉及到代表 - 我很难看到大局...) – Asaf 2010-10-16 21:37:00

23

由于.NET 3.5,你也可以使用System.Action代表,这将导致如下界面:

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

    public event Action Started; 
} 
+0

+1。我发现Action/Func比传统委托类型更加优雅(并且可读),并且您可以在界面中定义它们。 – chrnola 2014-04-07 17:39:28

0

派生类中继承的界面会提醒您定义和连接起来的东西你在里面宣布。

但你可能还需要明确地使用它,你仍然需要把它关联到一个对象。

例如使用控制模式的反转:

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

3

刚刚露出委托作为财产

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

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