2010-03-14 103 views
6

我正在從EmguCV擴展ImageBox控件。控件的Image屬性可以設置爲任何實現IImage接口的內容。通用類中的C#調用方法

以下所有實現此接口的:

Image<Bgr, Byte> 
Image<Ycc, Byte> 
Image<Hsv, Byte> 

現在我想打電話給Draw方法,上述類型(它可能是什麼都)的對象。

問題是當我訪問Image屬性時,返回類型是IImage。 IImage不實施Draw方法,但以上都是。

我相信我可以將IImage類型的對象轉換爲上面的一個(正確的),我可以訪問Draw方法。但我怎麼知道正確的是什麼?如果你有更好的方法來做到這一點,請同樣建議。

編輯

對不起,我忘了提的一個重要信息。上述每個類的Draw方法都有一個不同的參數。對於例如Draw對於Image<Bgr, Byte>需要Bgr類型的參數,而Draw對於Image<Hsv, Byte>需要採用類型爲Hsv的參數。

+0

是否有權訪問IImage和圖像代碼? –

+0

EmguCV是一個開源項目,儘管我更喜歡使用它們的二進制文件:) – Aishwar

+0

它看起來並不像圖像界面/實現設計得很好。 –

回答

0

怎麼是這樣的:

void foo(IImage image) 
{ 
    if (image is Image<Bgr, Byte>) 
    { 
     ((Image<Bgr, Byte>)(image)).Draw(); 
    } 

    // handle the other types the same way. 
} 
+3

我認爲最好有一個實現,而不是許多ifs。 –

+2

這只是乞求潦草的代碼。現在,對於每種類型,您都必須在多個地方添加代碼。將這個邏輯和所有不同圖像類型的邏輯外推到某種渲染器中可能會比這樣做更好。 –

+0

我同意還有其他很好的答案,這通常可能會導致非常草率的代碼。但就我而言,我只需要做一次,我不想編輯EmguCV源文件。我使用了這個,所以我會將其標記爲已接受。 – Aishwar

1

如果我理解正確的,你 - 圖片類實現繪製方法。我不知道你將如何使用它,但你可以這樣做:

private void DrawImage<T1, T2>(Image<T1, T2> image) 
{ 
    image.Draw(); 
} 

關於上述的主要問題是,上述方法的調用者應指定T1和T2類型。

如果您還沒有關於IIMAGE接口和它的實現控制那麼我認爲你會從兩個方案進行選擇:指定T1和T2類型或具有IFS /開關與所有可能的IIMAGE實現。

如果您有機會獲得IIMAGE接口和圖像類,那麼你應該增加通用IIMAGE接口,並添加Draw方法吧。

+0

這種方式你需要不同的泛型類型的不同方法。 – JohnIdol

+0

爲什麼?您只需使用必要的類型參數調用上述方法。 –

0

如果你確保圖像< T,U >,您有(不分類型)將有抽獎的方法,你可以使用反射和黑客周圍:

我會做它作爲一種擴展方法:

public static void Draw(this IImage image) 
{ 
    var method = image.GetType().GetMethod("Draw"); 
    if(method != null) 
    { 
     method.Invoke(image,null); 
    } 
} 

有點破解,但後來再說一次,我會說API的設計不正確。應該至少有一些抽屜類或什麼東西,會知道如何在圖像上採取行動。

+0

這會很慢。 –

+0

過早優化多少? – BFree

+0

不,反射速度很慢,並且提出的固溶不是如何使用反射的自然方式。 –

1

你應該有一個共同的接口,增加了抽獎()。

3

添加從IIMAGE繼承的IDrawableImage。

public interface IDrawableImage : IImage 
{ 
    void Draw(object val); 
    void Draw(); 
} 

然後,您只需做到以下幾點:如果你知道類型

public interface IDrawableImage<T, B> : IDrawableImage where B : byte 
{ 
    void Draw<T>(T val); 
} 

然後:

var value = new Hvr(); 
var drawableImage = container.Image as IDrawableImage<Hvr, Byte>; 
if (drawableImage != null) 
    drawableImage.Draw(value); 

如果

var drawableImage = container.Image as IDrawableImage; 
if (drawableImage != null) 
    drawableImage.Draw(); 

要匹配你的澄清以上你不要

var value = new Hvr(); 
var drawableImage = container.Image as IDrawableImage; 
if (drawableImage != null) 
    drawableImage.Draw(value); 
+2

這是爲這些問題創建接口的最佳實踐。檢查每個實現(如Adel的示例)違反了打開/關閉原則(http://en.wikipedia.org/wiki/Open/closed_principle)並創建了高度耦合(http://en.wikipedia.org/wiki/Coupling_ %28computer_science%29)。通過這個界面,你可以創建一個新的'Image '類型,並在不改變任何調用'Draw'方法的代碼的情況下使用它。 – Ronald

+0

這就是爲什麼我提出這種方法,做大的if語句在後面比我多得多,尤其是當你開始在任何地方開始時。突然之間,您需要一篇關於如何向其添加新類型的內部wiki文章,因爲它觸及瞭如此多的代碼。 –

0

您的問題缺少一條關鍵信息:您想寫的代碼。

我們需要知道您打算如何編寫調用Draw(...)方法的代碼。

0

或者,您可以使用動態方法並抓住機會。