在控件之间连接常见功能

xof*_*ofz 1 c# interface

我不确定如何提出这个问题.假设我有一个类需要访问Control的某些属性(例如,Visible和Location).也许我想使用同一个类来访问具有相同名称的另一个项的属性,但该类可能不是从Control派生的.所以我尝试制作一个界面:

public interface IThumbnail {

    bool    Visible     { get; set; }
    int     Height      { get; set; }
    int     Width       { get; set; }
    Image   Image       { get; set; }
    Point   Location    { get; set; }

    event EventHandler Click;
}
Run Code Online (Sandbox Code Playgroud)

请注意,例如,PictureBox碰巧实现了此接口.但是,因为类定义没有说它实现了IThumbnail,所以我无法将PictureBoxes转换为IThumbnails - 我在运行时得到了InvalidCastException.但是为什么CLR不能"弄清楚"PictureBox确实实现了IThumbnail(它只是没有明确地说它确实如此).

另外,我该怎么做才能处理这种情况?我想要一种方法来访问一些 PictureBox的属性,而不让我的类知道它正在修改PictureBox.

谢谢,山姆

PS-我是接口编程的新手,所以如果这是一个愚蠢的问题我很抱歉.

Gre*_*g D 5

这不是一个愚蠢的问题,它是一个很好的问题.:)

你在界面上要求的通常被称为" 鸭子打字".它目前不受支持,但C#4.0将通过新的" dynamic"关键字支持它.

在这一点上,你真的有三个选择我知道:

  1. 您可以上到树,直到找到共同的祖先(可能Component),然后向下转换为您支持的类型.如果堕落失败,你可以适当地投掷或处理.

    Pro:最小代码重复.

    Con:对于运行时类型的安全性,您正在远离编译时类型安全性.您必须为无效的强制转换添加错误检查/处理.

    码:

    public void UseThumbnail(Component c) 
    {
        PictureBox p = c as PictureBox;
        if(p != null) // do whatever
        // so forth
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您可以根据实现此功能所需的所有内容复制功能.

    Pro:保持编译时类型安全

    Con:你正在复制不同类型的代码.这可能会成为一个重大的维护负担,特别是如果您处理两个以上类似的类.

    码:

    public void UsePictureBox(PictureBox p)
    {
        // Some code X
    }
    
    public void UseOtherControl(OtherControl p)
    {
        // Some code X
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 您可以创建特殊接口并为要支持的类创建子类,以公开该常用功能.

    Pro:您可以获得编译时安全性并可以针对您的新界面进行编程.

    Con:您必须为要处理的所有内容添加一个空子类,并且需要使用它们.

    码:

    public class ThumbnailPictureBox : PictureBox, IThumbnail 
    { }
    
    Run Code Online (Sandbox Code Playgroud)