如何知道基类中的派生类

本文关键字:派生 何知道 基类 | 更新日期: 2023-09-27 18:25:42

我已经到处搜索了,找不到任何类似的人。我是C#的新手,在非面向对象语言方面工作了15年,所以我希望我没有错过一些简单的东西。

我正在尝试制作一个标准的Winform,它被继承了,这样我就不需要每次都重复我使用的代码(.Net多年来的乐趣之一是能够将事情集中化)。

我的问题是,当从MDI启动时,我想实现将派生类调用为"单实例"或"多实例"的能力,经过大量搜索,我几乎已经使用"泛型"实现了这一点。但我一直纠结于如何知道当前表单是哪个类,将其传递给泛型类以关闭表单

我的代码的简化版本将有助于理解我的问题。这是我为启动和关闭表单而设计的泛型类。它确定T的实例是否已经存在,这取决于你是启动单个实例还是多个实例,它要么显示它,要么创建表单的新实例。的MDI在启动方法中传递,使我可以将新表单附加到它。

public class FormLaunch<T> where T : MyBaseForm, new()
{
    public static T Instance;
    public static void LaunchultipleInstnace(FRMMDI mdi)
    {
        Instance = new T();
        Instance.MdiParent = mdi;
        Instance.Show();
        Instance.BringToFront();
    }
    public static void LaunchSingleInstance(FRMMDI mdi)
    {
        if (Instance == null) Instance = new T();
        Instance.MdiParent = mdi;
        Instance.Show();
        Instance.BringToFront();
    }
    public static void CloseInstance()
    {
        Instance = null;
    }
}

使用以下语句从MDI启动表单的"单实例"版本。

        FormLaunch<MyDerivedClass>.LaunchSingleInstance(this);

问题来了,我想在基本形式中处理一次形式的关闭,而不必每次在派生形式中都这样做。但我不知道该怎么做。

public partial class MyBaseForm : Form
{
    public MyBaseForm()
    {
        InitializeComponent();
    }
    private void MyBaseForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        FormLaunch<this.GetType()>.CloseInstance();
    }
}

但是这个。GetType()不起作用。如果我只是直接使用这个表单而不是继承它,我可以使用

        FormLaunch<MyBaseForm>.CloseInstance();

或者,如果我在每个派生类中处理FormClosed事件,那么我就可以使用

        FormLaunch<MyDerivedClass>.CloseInstance();

但我真的想这样做,以防止我每次在派生类中都忘记这样做。。。因为我几个月前写过这篇文章,每次使用它时都已经忘记了很多。

编辑:我的问题是,在中,我应该通过什么来代替T

        FormLaunch<T>.CloseInstance()

这需要引用派生类,而我似乎找不到。这GetType()引用了正确的玻璃,但不起作用。

如何知道基类中的派生类

如果你只想编辑打开的表单的单个实例,你可以阅读Jon Skeet对这个问题的回答

还有另外两点。

  • 您混合了不同的东西:.NET泛型和继承。
    • this.GetType()返回描述当前实例类(this)的System.Type类的实例
    • GenericClass<TypeParameter>中的类型参数只是使用中的具体类的名称,或者是泛型类定义中的一个类型参数名称:Generic<TParam>
  • 不能定义泛型控件类或窗体类。设计器无法序列化它们

您可以简单地在LaunchSingleInstance()中订阅FormClosed,并从表单本身完全删除关闭事件的处理:

public static void LaunchSingleInstance(FRMMDI mdi)
{
    if (Instance == null)
    {
        Instance = new T();
        Instance.FormClosed += (s, e) => CloseInstance();
    }
    Instance.MdiParent = mdi;
    Instance.Show();
    Instance.BringToFront();
}

一个更直接的答案-使用反射是可能的:

typeof(FormLaunch<>).MakeGenericType(this.GetType())
                    .GetMethod("CloseInstance")
                    .Invoke(null, null);