如何知道基类中的派生类

时间:2013-07-31 10:07:48

标签: c# winforms generics inheritance mdi

我在这里搜索到了所有人都找不到类似的东西。我是C#的新手,用非面向对象的语言工作了15年,所以我希望我不会错过任何简单的东西。

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

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

我的代码的简化版本将有助于理解我的问题。这是我用于启动和关闭表单的通用类。它确定T的Instance是否已存在,具体取决于您是启动单个实例还是多个实例,它是显示该实例还是创建表单的新实例。 MDI for在启动方法中传递,以允许我将新表单附加到该表单。

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()

这需要引用派生类,我似乎无法找到它。 this.GetType()指的是正确的玻璃,但不起作用。

2 个答案:

答案 0 :(得分:2)

如果你想要的只是打开单个表格实例,你可以阅读Jon Skeetthis question的答案

还有一对其他点。

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

答案 1 :(得分:1)

您只需订阅FormClosed中的LaunchSingleInstance(),然后完全删除表单中关闭事件的处理:

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);