表单和用户控件的基础 class

One base class for both forms and user controls

我有一个 Form 有几种输入验证方法。我希望在多个 FormUserControl 之间共享此验证逻辑。 base class 的类型应该是什么?它不能是 Form,因为它也将用于 UserControl,它不能是 UserControl,因为它也将用于 Form

我的直觉告诉我,解决方案可能涉及泛型,但我不确定。

注: By "validation logic" 我指的是实现,所以接口不是解决方案。


编辑(使问题更清楚一点):确实有一个单独的class用于实际验证输入。但是,我使用 ErrorProvider 来指示用户输入无效。我的 InputValidator class 使用 ErrorProvider 调用 Form/UserControl 中的一个方法向用户显示错误。我只是不想为每个 Form/UserControl.

复制粘贴此方法

您不能创建同时处理 Forms 和 UserControls 的基础 class。但是,您可以为您的表单创建一个基础 class,为您的用户控件创建另一个基础。

此外,创建一个接口,基 classes 实现并发布您需要在验证器中使用的成员。

通过这种方法,重复的代码量至少减少到两个位置。请注意,有些 OOP 实践在 Windows 表单(例如抽象 classes)的上下文中不起作用,因为设计者引入了一些限制。


原回答:
在这种情况下,最好的选择是将验证逻辑移动到它自己的单独 class 中。您可以在窗体和用户控件中使用这个新的 class。

如果在验证时需要引用Form或UserControl,可以使用ContainerControl类型的参数。此 class 是 Form 和 UserControl 的基础 class。这样,您可以创建适用于所有继承自 ContainerControl 的 class 的共享逻辑。

使用组合而不是继承。参见:Composition over inheritance(维基百科)。

您的表单必须继承自 Form 或继承自 Form 的另一个表单。您的用户控件必须继承自 UserControl 或继承自 UserControl 的另一个用户控件。您无法更改此设置,因此您无法为它们提供自己的基础 class。

相反,在单独的 class 中实现您的验证逻辑,并在您的表单和用户控件中使用它。

public partial class MyForm : Form
{
    private readonly MyValidation _validation;

    public Myform()
    {
        InitializeComponent();
        _validation = new MyValidation(errorProvider1);
    }

    //TODO: use _validation instead of inherited validation logic.
}

由于我不知道您的验证是什么,因此我无法为您提供有关如何准确实施此功能的更多详细信息。

第一件事是第一 - 我认为 Olivier 的回答非常好,我建议你使用它。
但是,虽然您不能更改 FormUserControl 的基础 classes,但仍然有一种方法可以使用接口和扩展方法仅编写一次方法 - 这这就是我想在此处的回答中显示的内容。

接口:

internal interface IValidatable
{
    ErrorProvider ErrorProvider {get;} 
}

分机 class:

internal static class IValidatableExtensions
{
    internal void ShowValidationResult(this IValidatable self, ValidationResult result)
    {
    // Here you can use self.ErrorProvider to show your results
    }
}

现在您可以让您的表单和用户控件实现 IVilidatable 接口,并且在验证 class 中只需调用 ShowValidationResult 方法。

同样,我会简单地向验证实例发送对 errorProvider 的引用,正如 Olivier 在他的回答中所展示的那样,但这种技术在其他情况下可能会有用,所以我想我最好自己添加一个答案。