简体   繁体   中英

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 eg 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.

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

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.

你应该有一个添加Draw()的共享接口。

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.
}

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.

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.

或者,您可以使用动态方法并抓住机会。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM