我正在处理一个遗留应用程序,由于继承关系存在一些缺陷,但我很难妥善解决它。
目前,WinForms的结构如下:
- BaseForm - ListViewForm : BaseForm - ListViewFormReadOnly : ListViewForm - ListViewFormWithDetailForm : ListViewForm - DetailForm : BaseForm - ConcreteForm : ListViewFormWithDetailForm
在BaseForm中有一个名为“InitializeMyStuff()”的方法,是被继承实例覆盖的虚拟方法。
例如:
正如您所想象的那样,这会带来一些问题,例如: - “在这一点上我必须设置哪些东西才能使表单工作” - “哪些东西可能还没有初始化?” - “哪些属性和方法调用可以使用?” 以及关于那个神奇的黑匣子中可能发生的事情的一些其他有趣想法。
我该如何重构代码,以便更清楚地了解正在发生的事情?请记住,这是一个具有约150个或更多具体表单的项目。
我的初始想法是将这些神奇的属性(例如
例如,像这样:
我在这里遇到的问题是:ListForm的FormConfig对象必须具有其他属性,例如
// 编辑:将代码整理到实际发生的情况,并消除构造函数中的虚拟调用违规。
目前,WinForms的结构如下:
- BaseForm - ListViewForm : BaseForm - ListViewFormReadOnly : ListViewForm - ListViewFormWithDetailForm : ListViewForm - DetailForm : BaseForm - ConcreteForm : ListViewFormWithDetailForm
在BaseForm中有一个名为“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
规则:http://msdn.microsoft.com/en-us/library/ms182331.aspx - 构造函数中不应调用虚方法。 - BartoszKPInitializeMyStuff
,在构造函数中进行虚拟调用是一个不好的想法,但这需要很多工作。 - Alessandro D'AndriaInitialiseMyStuff()
的调用移动到OnCreateControl()
的实现中,这避免了在构造函数中调用虚拟方法的问题,并且这也意味着您可以确保所有包含的控件在那时已经被创建。 - Matthew Watson