3

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

我正在尝试制作一个可以继承的标准 Winform,这样我就不需要重复我每次使用的代码(.Net 对我多年来使用的东西的乐趣之一就是能够将事情集中到很远的地方更多的)。

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

我的代码的简化版本将有助于理解我的问题。这是我为启动和关闭表单而设计的通用类。它确定 T 的实例是否已经存在,具体取决于您是启动单个实例还是多个实例,它要么显示,要么创建表单的新实例。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();
    }
}

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

        FormLaunch<MyBaseForm>.CloseInstance();

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

        FormLaunch<MyDerivedClass>.CloseInstance();

但我真的很想以一种方式做到这一点,让我每次都忘记在派生类中这样做......因为我几个月前写了这个,并且每次使用它时都已经忘记了。

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

        FormLaunch<T>.CloseInstance()

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

4

2 回答 2

2

如果您想要的只是打开表单的单个实例,您可以阅读Jon Skeet这个问题的回答

只是另外一点。

  • 你混合了不同的东西:.NET 泛型和继承。
    • this.GetType()返回一个类的实例System.Type,描述当前实例类 ( this),
    • 输入的类型参数GenericClass<TypeParameter>只是使用中的具体类的名称,或者是泛型类定义中的类型参数名称:Generic<TParam>
  • 您不能定义通用的 Control 或 Form 类。Designer 无法对它们进行序列化。
于 2013-07-31T11:53:40.130 回答
1

您可以简单地订阅FormClosedLaunchSingleInstance()从表单本身完全删除对关闭事件的处理:

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);
于 2013-07-31T10:19:33.580 回答