2

GUIで画像を変更するのに役立つクラスを作成しています。画像は、PictureBoxまたはのいずれかになりますDataGridViewImageCell。クラスは、変更可能なすべての画像をリストとして保存します。クラスの各インスタンスは、両方を使用するのではなく、いずれPictureBoxかを使用します。DataGridViewImageCells

両方の入力を処理する方法はありますか?のように、それらの間にいくつかの共通のインターフェースがありますか、またはそれらをいくつかの共通の親クラスにキャストする方法がありますか?

4

1 に答える 1

3

ええと、あなたはいつでもそれらをとして扱うことができますobject、しかし私はあなたのクラスがそれらの2つのタイプのために2つのオーバーロードを具体的に提供することを提案します:

class MyClass
{
    public void AddImage(PictureBox image)
    {

    }

    public void AddImage(DataGridViewImageCell image)
    {

    }
}

それを内部的にどのように保存するかはあなた次第です。おそらく、List<object>キャストイン/キャストアウトするものがあるか、タイプごとに1つずつ、2つの別々のリストを維持するか、または単にそれぞれimageを含むオブジェクトの子コレクションに追加します。

共有クラスについては、MSDNから、基本クラス以外は共有しないとObject思います。そのため、基本クラスに固執するか、独自の包含クラスでラップする必要があります。

編集:これは、ラッピングインターフェイスとファクトリでそれを処理するより完全に具体化された方法です。

objectまず、画像を渡すことができる共有ベースのタイプ(この場合)でインターフェースを定義します。

public interface IImageWrapper
{
    object RawImage { get; }
}

public class PictureBoxImageWrapper : IImageWrapper
{
    public object RawImage { get; private set; }

    public PictureBoxMyImage(PictureBox image)
    {
        this.RawImage = image;
    }
}

public class DataGridViewImageCellImageWrapper : IImageWrapper
{
    public object RawImage { get; private set; }

    public DataGridViewImageCellImageWrapper(DataGridViewImageCell image)
    {
        this.RawImage = image;
    }
}

次に、ユーザーAPIが画像をラップし、どの画像タイプが厳密にサポートされているかについてコンパイル時の安全性を確保するための単純なファクトリです。

public class ImageWrapperFactory
{
    public IImageWrapper Create(PictureBox image)
    {
        return new PictureBoxImageWrapper(image);
    }

    public IImageWrapper Create(DataGridViewImageCell image)
    {
        return new DataGridViewImageCellImageWrapper(image);
    }
}

次に、表示しているクラスまたはビューがこれらのIImageWrapperオブジェクトを受け取り、使用可能なタイプに変換できます。

public class MyDisplayClass
{
    private List<IImageWrapper> Images = new List<IImageWrapper>();

    public void AddImage(IImageWrapper image)
    {
        Images.Add(image);
    }

    private void AddImageToContainer(IImageWrapper image)
    {
        object rawImage = image.RawImage;

        if (rawImage is PictureBox)
            AddImageToContainerImpl((PictureBox)rawImage);
        else if (rawImage is DataGridViewImageCell)
            AddImageToContainerImpl((DataGridViewImageCell)rawImage);
        else
            throw new NotSupportedException();
    }

    private void AddImageToContainerImpl(PictureBox image)
    {
        //add to container
    }

    private void AddImageToContainerImpl(DataGridViewImageCell image)
    {
        //add to container
    }
}

いくつかの使用例:

PictureBox myImage = ...
MyDisplayClass myView = ...

myView.AddImage(ImageWrapperFactory.Create(myImage));

このように、画像の基になるタイプはあまり強く強制されていません。必要に応じて、ファクトリを更新して、厳密に型指定されたオブジェクトを返すことができます。これにより、表示クラスがサポートされているIImageWrapperオブジェクトに対して強く型付けされますが、それは目的に反します(最初の回答のように/に対して強く型付けすることもできます)。 。PictureBoxImageWrapperPictureBoxDataGridViewImageCell

編集:さらに別の方法は、「ファクトリ」に暗黙の演算子を活用することです。このようにして、APIは生の画像オブジェクトを「渡す」だけであり、それらがサポートされている場合は、暗黙の演算子が見つかります。そうでない場合は、コンパイル時の例外が発生します。

public sealed class ImageWrapper
{
    public object RawData { get; private set; }

    private ImageWrapper(object rawData)
    {
        this.RawData = rawData;
    }

    public static implicit operator ImageWrapper(PictureBox image)
    {
        return new ImageWrapper(image);
    }

    public static implicit operator ImageWrapper(DataGridViewImageCell image)
    {
        return new ImageWrapper(image);
    }
}


PictureBox myImage = ...
ImageControl unsupportedImage = ... 
MyDisplayClass myView = ...

myView.AddImage(myImage); //OK!
myView.AddImage(unsupportedImage);// compile error!
于 2013-01-22T16:18:59.097 に答える