【发布时间】:2013-10-07 11:47:10
【问题描述】:
我正在开发一个遗留应用程序,由于继承而存在一些缺陷,但我正在努力正确解决它。
目前 WinForms 的结构如下所示:
BaseFormListViewForm : BaseFormListViewFormReadOnly : ListViewFormListViewFormWithDetailForm : ListViewFormDetailForm : BaseFormConcreteForm : ListViewFormWithDetailForm
BaseForm 中有一个方法叫做 protected virtual void InitializeMyStuff(),它会在继承的实例中被覆盖。
例如
public class BaseForm {
public BaseForm() {
//.. do stuff
//.. do other stuff like initialize DB connection or read app.config values and initialize properties..
}
public virtual void InitializeMyStuff() {
throw new NotImplementedException();
}
}
public class ListViewForm : BaseForm {
protected BindingSource GridBindingSource { get; set; }
public ListViewForm {
//do special stuff like adding the grid and some buttons
}
}
public class ConcreteForm : ListViewForm {
public override void InitializeMyStuff() {
GridBindingSource = my_bindingSource;
SomeOtherUsefulProperty = myValue;
Foo = new Bar();
// etc.
}
}
//Usage:
var myForm = new ConcreteForm();
myForm.InitializeMyStuff();
您可以想象,这会产生一些问题,例如: -“此时我必须设置哪些内容才能使表单正常工作” - “什么东西可能还没有初始化?” - “我可以使用哪些属性和方法调用” 以及关于那个魔法黑匣子中可能发生的其他一些有趣的想法。
我怎样才能重构它,以便更清楚地知道发生了什么?请记住,这是一个包含大约 150 个或更多具体表格的项目。
我最初的想法是将GridBindingSource 之类的神奇属性封装到一个对象中(例如FormConfiguration),并在BaseForm 中将其设为私有。
例如类似的东西
public class BaseForm {
private FormConfigObject _formConfig = new FormConfigObject();
protected override void OnLoad()
{
InitializeMyStuff(_formConfig);
}
protected virtual void InitializeMyStuff(FormConfigObject config)
{}
}
我在这里遇到的问题是:ListForm 的 FormConfig 对象必须具有其他属性,例如 GridBindingSource 但我不能只将派生类中的签名更改为 ListFormConfigObject 而不是FormConfigObject..
任何人都可以提出可能的解决方案来摆脱这种困境吗?
// 编辑:将代码理顺到实际发生的情况,并消除构造函数违规中的虚拟调用。
【问题讨论】:
-
这也违反了
CA2214规则:msdn.microsoft.com/en-us/library/ms182331.aspx - 不应在构造函数中调用虚方法。 -
你有什么好的理由来改变它吗?起初我的想法是完全删除
InitializeMyStuff,在 ctor 中进行虚拟调用是个坏主意,但这是很多工作。 -
这个问题可能更适合codereview.stackexchange.com
-
是的,虚拟调用实际上隐藏在其他方法的层次结构中,实际应用程序要复杂得多。对不起,我的示例代码中的那个错误:/
-
BaseForm 实际上是 Form(或 Control)类型吗?如果是这样,您或许可以将对
InitialiseMyStuff()的调用移动到OnCreateControl()的实现中,这样可以避免在构造函数中调用虚方法的问题,这也意味着您可以确保所有包含的控件都已创建到那时。
标签: c# .net winforms design-patterns inheritance