我有一个Form
,有几种输入验证方法。我希望在几个Form
和UserControl
之间共享此验证逻辑。什么应该是基类的类型?它不能是Form
,因为它也会用于UserControl
,它不能是UserControl
,因为它也会用于Form
。
我的直觉告诉我,解决方案可能涉及泛型,但我不确定。
注意:“验证逻辑”我指的是实现,因此接口不是解决方案。
编辑(使问题更清晰):我做有一个单独的类来实际验证输入。但是,我使用ErrorProvider
来指示用户输入无效。我的InputValidator
类使用Form
调用UserControl
/ ErrorProvider
内的方法向用户显示错误。我只是不想为每个Form
/ UserControl
复制粘贴此方法。
答案 0 :(得分:3)
您无法创建同时处理Forms和UserControls的基类。但是,您可以为表单创建基类,为UserControls创建另一个基类。
此外,创建一个接口,两个基类都实现并发布您需要在验证器中使用的成员。
通过这种方法,重复的代码量至少减少到两个位置。请注意,有一些OOP实践在Windows窗体(例如抽象类)的上下文中不起作用,因为设计者引入了一些限制。
原始答案:
在这种情况下,最好的选择是将验证逻辑移动到它自己的单独类中。您可以使用Forms和UserControls中的这个新类。
如果您需要在验证期间引用Form或UserControl,则可以使用ContainerControl类型的参数。此类是Form和UserControl的基类。这样,您就可以创建适用于从ContainerControl继承的所有类的共享逻辑。
答案 1 :(得分:2)
使用合成而不是继承。请参阅:Composition over inheritance(维基百科)。
您的表单必须继承自Form
或其他继承自Form
的表单。您的用户控件必须继承自UserControl
或继承自UserControl
的其他用户控件。你不能改变它,因此你不能为它们提供自己的基类。
相反,请在单独的类中实现验证逻辑,并在表单和用户控件中使用它。
public partial class MyForm : Form
{
private readonly MyValidation _validation;
public Myform()
{
InitializeComponent();
_validation = new MyValidation(errorProvider1);
}
//TODO: use _validation instead of inherited validation logic.
}
我无法向您提供有关如何准确实现此问题的更多详细信息,因为我不知道您的验证是什么。
答案 2 :(得分:1)
首先是第一件事 - 我认为Olivier的答案非常好,我建议你使用它。
但是,虽然您无法更改Form
和UserControl
的基类,但仍然有一种方法只使用接口和扩展方法编写一次方法 - 这就是我的意思我想在这里给出答案。
界面:
internal interface IValidatable
{
ErrorProvider ErrorProvider {get;}
}
扩展类:
internal static class IValidatableExtensions
{
internal void ShowValidationResult(this IValidatable self, ValidationResult result)
{
// Here you can use self.ErrorProvider to show your results
}
}
现在,您可以让表单和用户控件实现IVilidatable
接口,在验证类中只需调用ShowValidationResult
方法。
同样,我只是简单地向验证实例发送一个对errorProvider的引用,正如Olivier在他的回答中所证明的那样,但是这种技术在其他情况下可能会有用,所以我想我最好自己添加一个答案。