Aishwar
Aishwar

Reputation: 9714

C# Calling Methods in Generic Classes

I am extending the ImageBox control from EmguCV. The control's Image property can be set to anything implementing the IImage interface.

All of the following implement this interface:

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

Now I want to call the Draw method on the object of the above type (what ever it may be).

The problem is when I access the Image property, the return type is IImage. IImage does not implement the Draw method, but all of the above do.

I believe I can cast the object of type IImage to one of the above (the right one) and I can access the Draw method. But how do I know what the right one is? If you have a better way of doing this, please suggest that as well.

EDIT

Sorry, but I forgot to mention an important piece of information. The Draw method for each of the above class takes one different argument. For e.g. Draw for Image<Bgr, Byte> takes an argument of type Bgr and the Draw for Image<Hsv, Byte> takes an argument of type Hsv instead.

Upvotes: 6

Views: 1844

Answers (7)

Ilya Smagin
Ilya Smagin

Reputation: 6152

Or, you can use dynamic methods and take your chances.

Upvotes: 0

Bryan Watts
Bryan Watts

Reputation: 45445

Your question is missing a critical piece of information: the code you would like to write.

We need to know how you intend to write the code which calls the Draw(...) method.

Upvotes: 0

Andrew Bezzub
Andrew Bezzub

Reputation: 16032

If I understood you correctly - Image class implements draw method. I don't know how you are going to use it, but you can do in this way:

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

The main problem about above is that the caller of the above method should specify the T1 and T2 types.

If you don't have control about IImage interface and its implementations then I think you will be choosing from two solutions: specify T1 and T2 types or having ifs/switches with all possible IImage implementations.

If you have access to the IImage interface and Image class then you should add generic IImage interface and add Draw method to it.

Upvotes: 1

Tom Anderson
Tom Anderson

Reputation: 10827

Add an IDrawableImage that inherits from IImage.

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

Then you can simply do the following:

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

To match your clarification above:

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

then if you know the type:

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

if you don't

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

Upvotes: 3

s_hewitt
s_hewitt

Reputation: 4302

You'll should have a shared interface that adds Draw().

Upvotes: 1

BFree
BFree

Reputation: 103740

If you're sure that the Image<T,U> that you'll have (regardless of the types) will have the Draw method, you can use reflection and hack around it:

I would do it as an extension method:

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

A bit of a hack, but then again, I would say that the API isn't properly designed. There should at least be some Drawer class or something that would know how to act on an image.

Upvotes: 0

Adel Hazzah
Adel Hazzah

Reputation: 8937

How about something like this:

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

    // handle the other types the same way.
}

Upvotes: 0

Related Questions