1

我的 winforms 框架中有以下表格

  • FormBase(继承自 Form)
  • FormBaseList(继承自 FormBase)
  • FormBaseDetail(继承自 FormBase)

现在应用程序中的每个表单都继承自上述 3 个表单之一。
例如FormCustomerList将继承自FormBaseList

现在FormBaseList事件FormBaseList_Shown存在(通过在 VS 的属性窗口中双击它)

我想在代码中知道FormBaseList_Show是否存在事件FormCustomerList_Show(再次在属性窗口中双击它)。

这甚至可能吗?

那我为什么要这个?
因为框架中的某些更改要求表单不再使用Shown事件,而是使用自定义事件。
如果他向表单添加事件,我想捕捉并向开发人员显示警告,Show如果确实需要,他可以设置一个隐藏此警告的属性。
这个警告不需要在设计时显示,在运行时就足够了。但是,如果它在设计时可能,那将是一个奖励。
那么这可以做到吗,是否有更好的方法来做到这一点?

我希望这个解释清楚

编辑

这个想法是,当开发人员使用 Show 事件时,他必须得到警告(在设计时或运行时)。如果他觉得他真的需要 Show 方法,他应该能够为这个特定的表单设置警告

4

3 回答 3

1

您应该以Shown这种方式隐藏事件并弃用它:

[Obsolete("Shown event is deprecated.")]
public new event EventHandler Shown
{
    add { base.Shown += value; }
    remove { base.Shown -= value; }
}

您已将其标记为过时,当您构建解决方案时,它会在编译时在错误列表窗口中显示警告。

此外,通过订阅Shown基地的原始事件,该事件将继续按预期工作。

要禁用警告,请在已订阅事件的表单的 Designer.cs 文件顶部添加以下代码行:

#pragma warning disable CS0618 // Type or member is obsolete

并将这一行添加到底部:

#pragma warning restore CS0618 // Type or member is obsolete

注意:在除designer.cs 文件之外的其他文件中,仅将事件处理程序订阅用. 包围就足够了#pragma。但是对于designer.cs,您不能围绕事件处理程序订阅,因为通过更改设计器中的任何内容,InitializeComponent定义成员变量的内容和代码块将自动生成,并且您在designer.cs中的所有手动更改都将丢失. 但是如果你放在#pragma文件的顶部和底部,它是安全的,不会从 Designer.cs 中删除。

于 2019-05-03T01:00:47.307 回答
1

要在运行时抛出异常或显示消息框,您有以下选项:

  • 隐藏Shown事件并在add部分中抛出异常(除非已设置跳过标志)。
  • 使用反射查找事件的事件处理程序列表Shown并检查是否有附加到事件的处理程序。

在这两种解决方案中,都可以使用布尔属性来覆盖派生形式中的行为。

选项 1 - Shadowing Shown 事件并将代码添加到add

您可以隐藏Shown事件并在add访问器中添加代码以显示消息框或在将处理程序添加到事件时抛出异常。

在下面的示例中,我已将ThrowExceptionOnSubscribingShownEvent属性添加到默认情况下的基本表单,这意味着它会在订阅事件true时引发异常。Shown

public bool ThorwExceptionOnSubscribingShownEvent { get; set; } = true;

public new event EventHandler Shown
{
    add
    {
        if (ThorwExceptionOnSubscribingShownEvent)
            throw new InvalidOperationException("Shown event is deprecated.");

        base.Shown += value;
    }
    remove
    {
        base.Shown -= value;
    }
}

Shown选项 2 - 查找事件的事件处理程序列表

作为运行时的一个选项,您可以覆盖OnShown方法并使用反射,获取EVENT_SHOWN字段并使用它,获取事件的事件处理程序列表Shown。然后可以检查事件处理程序列表是否为空,抛出异常。

在下面的示例中,我已将ThrowExceptionOnSubscribingShownEvent属性添加到默认情况下的基本表单,这意味着它会在订阅事件true时引发异常。Shown您可以false在派生形式中将其设置为:

public partial class BaseForm : Form
{
    public BaseForm()
    {
        InitializeComponent();
    }

    public bool ThrowExceptionOnSubscribingShownEvent { get; set; } = true;
    protected override void OnShown(EventArgs e)
    {
        if (!DesignMode)
        {
            var EVENT_SHOWN = typeof(Form).GetField("EVENT_SHOWN",
                BindingFlags.NonPublic | BindingFlags.Static)
                .GetValue(null);
            var handlers = Events[EVENT_SHOWN]?.GetInvocationList();
            if (ThrowExceptionOnSubscribingShownEvent && handlers?.Length > 0)
                throw new InvalidOperationException("Shown event is deprecated.");
        }
        base.OnShown(e);
    }
}
于 2019-05-03T14:54:11.550 回答
0

使用反射可能是可能的,但它会相当混乱。更好的策略是像这样隐藏 Shown 事件:

        [Obsolete("Don't use this event, use my custom one")]
        public new event EventHandler Shown;

然后任何试图使用这个事件的东西都会产生编译器警告。

于 2019-05-02T12:29:29.507 回答