C#在泛型类中调用方法

C#在泛型类中调用方法,c#,.net,generics,casting,C#,.net,Generics,Casting,我正在从EmguCV扩展ImageBox控件。控件的Image属性可以设置为实现IImage接口的任何内容 以下所有操作都实现此接口: Image<Bgr, Byte> Image<Ycc, Byte> Image<Hsv, Byte> 图像 形象 形象 现在我想对上述类型的对象调用Draw方法(不管它是什么) 问题是当我访问Image属性时,返回类型是IImage。IImage不实现Draw方法,但上述所有方法都实现了 我相信我可以将IImage类型的对

我正在从EmguCV扩展ImageBox控件。控件的
Image
属性可以设置为实现
IImage
接口的任何内容

以下所有操作都实现此接口:

Image<Bgr, Byte>
Image<Ycc, Byte>
Image<Hsv, Byte>
图像
形象
形象
现在我想对上述类型的对象调用
Draw
方法(不管它是什么)

问题是当我访问Image属性时,返回类型是
IImage
。IImage不实现
Draw
方法,但上述所有方法都实现了

我相信我可以将
IImage
类型的对象强制转换为上面的一个对象(右侧),并且我可以访问
Draw
方法。但是我怎么知道正确的是什么呢?如果你有更好的方法,也请提出建议

编辑


对不起,我忘了提一条重要的信息。上述每个类的Draw方法都使用一个不同的参数。例如,
Draw
For
Image
采用类型为
Bgr
的参数,而
Draw
For
Image
采用类型为
Hsv
的参数。

类似的情况如何:

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

    // handle the other types the same way.
}
void foo(IImage图像)
{
如果(图像是图像)
{
((图像)(图像)).Draw();
}
//以相同的方式处理其他类型。
}

如果我理解正确-Image类实现了draw方法。我不知道您将如何使用它,但您可以这样做:

private void DrawImage<T1, T2>(Image<T1, T2> image)
{
    image.Draw();
}
private void DrawImage(图像)
{
image.Draw();
}
上面提到的主要问题是,上述方法的调用方应该指定T1和T2类型

如果您无法控制IImage接口及其实现,那么我认为您将从两种解决方案中进行选择:指定T1和T2类型,或者在所有可能的IImage实现中使用ifs/开关


如果您有权访问IImage接口和Image类,那么您应该添加通用IImage接口并向其添加Draw方法。

如果您确定您将拥有的图像(无论类型)将具有Draw方法,您可以使用反射和破解:

我会将其作为一种扩展方法:

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

有点像黑客,但我要说的是,API设计得不正确。至少应该有一些抽屉类或知道如何处理图像的东西。

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

添加从IImage继承的IDrawableImage

public interface IDrawableImage : IImage
{
   void Draw(object val);
   void Draw();
}
然后,您可以简单地执行以下操作:

var drawableImage = container.Image as IDrawableImage;
if (drawableImage != null)
    drawableImage.Draw();
为了配合您的上述澄清:

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

您的问题缺少一条关键信息:您想要编写的代码


我们需要知道您打算如何编写调用
Draw(…)
方法的代码。

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

我认为最好使用一个实现,而不是多个ifs。这只是在乞求草率的代码。现在,对于每种类型,您都必须在多个位置添加代码。将此逻辑以及不同图像类型的所有逻辑外推到某种渲染器中可能比执行类似操作更好。我同意还有其他很好的答案,这通常会导致非常草率的代码。但在我的情况下,我只需要做一次,我不想编辑EmguCV源文件。我使用了这个,所以我会将它标记为已接受。这样,不同的泛型类型需要不同的方法。为什么?您只需使用必要的类型参数调用上述方法。不,反射很慢,并且建议的解决方案不是使用反射的自然方式。如果您从MethodInfo创建一个委托并缓存它,而不是每次都查找它,反复调用不会很慢。你有权访问IImage和图像代码吗?EmguCV是一个开源项目,尽管我真的更喜欢使用它们的二进制文件:)看起来图像接口/实现设计得并不好。感谢所有回答的人。我学到了一些非常好的东西。通常,被接受的答案可能会导致非常草率的代码。但在我的情况下,我只需要做一次,我不想编辑EmguCV源文件。我使用了这个,所以我已经将它标记为已接受。为这类问题创建接口是一种最佳实践。检查每个实现(如Adel的示例中所示)违反了打开/关闭原则()并创建了高耦合()。使用此界面,您可以创建一个新的
图像
类型并使用它,而无需更改调用
绘图
方法的任何代码。这正是我建议使用此方法的原因,使用大型if语句多年来让我无法计数,尤其是当您开始在任何地方使用此方法时。突然之间,您需要一篇关于如何向其添加新类型的内部wiki文章,因为它涉及太多代码。
var value = new Hvr();
var drawableImage = container.Image as IDrawableImage<Hvr, Byte>;
if (drawableImage != null)
    drawableImage.Draw(value);
var value = new Hvr();
var drawableImage = container.Image as IDrawableImage;
if (drawableImage != null)
    drawableImage.Draw(value);