Windows Forms通用继承

5

我有这些类:

class Foo<T1, T2> : Form 
    where T1, T2 : EventArgs

class MiddleGoo : Foo<X,Y>

class Goo : MiddleGoo

X和Y只是从EventArgs派生的简单类。

我在设计器中看到了Goo,但我想创建一个类Boo,让它在Foo和Goo之间,就像这样:

class Boo<T1, Y> : Foo<T1, Y>
where T1 : EventArgs

class MiddleGoo : Boo<X,Y>

class Goo : MiddleGoo

无法使用中间类进行解决,有什么想法吗?

编辑:我的意思是Y和X是像YEventArgs和XEventArgs这样的类,我的问题是在我将Y定义为T2时,在设计类Boo中如何看到它,但仍希望通过T1保持其通用性。

编辑2:我刚意识到我拼错了Y类的某些内容...

public class Foo<T1, T2> : Form
    where T1 : EventArgs
    where T2 : EventArgs
{
}

public class Boo<T1> : Foo<T1, MyEventArgs2>
    where T1 : EventArgs
{
}

public class MiddleGoo : Boo<MyEventArgs1>
{
}

class Goo : MiddleGoo
{
}

public class MyEventArgs2 : EventArgs
{
}

public class MyEventArgs1 : EventArgs
{      
}

我想澄清一下,在设计师中我无法看到Boo...(MiddleGoo也看不到,但我不需要它)


3
"无法工作" - 为什么?出现了什么错误? - wingerse
2
假设Foo的声明没有改变,第二段代码肯定是无效的,因为Y不继承自EventArgs。这是你的“中间”类吗?这看起来像一个X-Y问题。你想做什么?Winforms设计器不喜欢_forms_,更不用说带有泛型参数的继承表单了。 - stuartd
只有在添加 Y:EventArgs 的情况下,class Boo<T1, Y> : Foo<T1, Y> where T1 : EventArgs 才是有效的。这里的 Y 是一个泛型参数名,它不是你所说的继承自 EventArgsY - Reza Aghaei
请看我的编辑,我觉得我没有清楚地表达我的问题。 - Plondrein
我纠正了我的类,这不仅仅是语法问题,它改变了我的问题的含义。 - Plondrein
显示剩余7条评论
2个回答

9

对于Visual Studio版本>= VS2015.1

VS2015.1开始,Windows Forms Designer可以正常显示具有泛型基类的类,因此在较新版本的VS中不再需要其他帖子中的解决方法,以下类将在设计器中显示而无需任何问题。

因此,有一个基本的泛型类如下:

public class BaseForm<TModel,TService> : Form
{
    public TModel Model {get;set;}
    public TService Service {get; set;}
}

您可以在设计器中轻松创建派生表单:

public class FooForm: BaseForm<Foo,FooService> 
{
}

Visual Studio的旧版本

在Visual Studio的旧版本中,当设计师想要在设计器中托管您的表单时,它会尝试创建您的表单的基类的实例,并且您的类必须具有非泛型基类,以便设计器可以显示它。

因此,您可以看到BaseForm<T>:Form可以在设计器中显示,但CategoryForm:BaseForm<Category>无法在设计器中显示。在这些情况下的解决方法是创建一个BaseCategoryForm:BaseForm<Category>,然后CategoryForm:BaseCategoryForm将在设计器中显示。

示例

假设这是您接受TModel作为模型和TService作为服务的基类:

public class BaseForm<TModel,TService> : Form
{
    public TModel Model {get;set;}
    public TService Service {get; set;}
}

然后,通过以下代码创建一个中间表单:
Public Class BaseFooForm: BaseForm<Foo, FooService>{ }

最终形式如下:

public class FooForm: BaseFooForm
{
}

现在最终的 FooForm 有设计师,您可以正常使用它。这样,您就可以创建支持设计师的类。
注意:
更新也应用于控件设计师。因此,在 WinForm UserControl 的通用基类 中,您不再需要针对 VS>=VS2015.1 进行此类解决方法。

1
"BaseForm<T>: 表单可以在设计器中显示,但需要在 Ctor 中添加泛型参数,如下所示:partial class BaseForm<T>" - BillW
1
@BillW 在所有情况下,构造函数应该与你的类定义相匹配。 - Reza Aghaei
如果您的继承链是“普通类->泛型<T>类->表单/用户控件”,那么它可以正常工作。但是,如果有两个或更多级别的泛型,它仍然会出现问题。 - Arno Peters

0

Foo类中的T2类型参数需要可转换为EventArgs。但是当您定义Boo类时,没有包含该约束条件。请将您的Boo类更改为以下内容:

class Boo<T1, Y> : Foo<T1, Y>
    where T1 : EventArgs
    where Y : EventArgs

此外,您在Foo类声明时遇到语法错误。请将其更改为:

class Foo<T1, T2>
    where T1 : EventArgs
    where T2 : EventArgs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接