Windows 窗体通用继承
Posted
技术标签:
【中文标题】Windows 窗体通用继承【英文标题】:Windows Forms Generic Inheritance 【发布时间】:2016-01-11 19:08:20 【问题描述】:我有这些课程:
class Foo<T1, T2> : Form
where T1, T2 : EventArgs
class MiddleGoo : Foo<X,Y>
class Goo : MiddleGoo
X,Y 只是从 EventArgs 派生的简单类。
我在设计器中看到了 Goo,但我想在 Foo 和 Goo 之间创建一个 Boo 类,如下所示:
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 保持它的通用性。
EDIT2:我刚刚意识到我拼错了关于 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
需要明确的是,我只是在 Designer 中看不到 Boo...(我也看不到 MiddleGoo,但我不需要)
【问题讨论】:
“不起作用” - 为什么?什么错误? 假设Foo
的声明没有改变,第二段代码肯定是无效的,因为Y
不是继承自EventArgs
。那是你的“中间”课程吗?这看起来像一个 X-Y 问题。你想做什么? Winforms 设计者不喜欢 forms,更不用说继承具有通用参数的表单了。
@stuartd 使用带有通用参数的表单有很多好处,但不幸的是设计师不支持它们,我在一个非常大的项目中使用带有通用参数的表单使用我描述的技巧here 和我有设计师支持,希望你看看并发现它有帮助:)
设计者需要创建一个基类的实例来完成它的工作,最明显的方面是所见即所得的外观。当基类是泛型时,这当然是不可能的,它不可能猜测选择哪个特定类型的参数。你可以让这个类在代码中工作,但你必须不使用点击视图。
class Boo<T1, Y> : Foo<T1, Y> where T1 : EventArgs
也只有加上Y:EventArgs
才有效,这里Y
是一个通用参数名,不是你说的Y
继承自EventArgs
【参考方案1】:
对于 Visual Studio 版本 >= VS2015.1
从 VS2015.1 开始,Windows 窗体设计器显示具有通用基类的类,没有任何问题。因此,较新版本的 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 作为 Model 和 TService 作为 Service 的基类,例如:
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
有了设计师,您可以正常使用它。这样您就可以创建设计器支持的类。
注意
此更新也适用于控件设计器。因此,在generic base class for WinForm UserControl 中,您不再需要 VS>=VS2015.1
的这种解决方法。
【讨论】:
"BaseFormFoo
类中的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
【讨论】:
以上是关于Windows 窗体通用继承的主要内容,如果未能解决你的问题,请参考以下文章