我有这种通用方法在面板中打开表单,此方法继承自Form
,目前限制它有一个空构造函数(where T : Form, new())
public void OpenForms<T>() where T : Form, new()
{
Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
if (form !=null)
{
//If the instance is minimized we leave it in its normal state
if (form.WindowState == FormWindowState.Minimized)
{
form.WindowState = FormWindowState.Normal;
}
//If the instance exists, I put it in the foreground
form.BringToFront();
return;
}
//The form opens
form = new T();
form.TopLevel = false;
container_panel.Controls.Add(form);
container_panel.Tag = form;
form.Show();
}
以这种方式来称呼它:
OpenForms<Form1>();
如何调整此函数以将参数传递给表单?
在这种情况下,我需要将两个参数传递给表单,如下所示:
OpenForms<Form1>(param1, param2);
并非所有表单都接收参数,但将来您可能需要使用1/2/3参数,具体取决于表单。
参数的类型可能有所不同:
bool
,string
,int
......
这可以收到这样的东西:
public void OpenForms<T>(params object[] args) where T : Form, new() { ... }
我们的想法是能够以下列方式使用它:
object[] args = new object[] { "a", true };
OpenForms<Form1>(args);
OpenForms<Form1>("a", 2, false);
OpenForms<Form1>();
收到参数后,您可以在创建表单时使用它们。
知道如何实现这个目标吗?
修改
我想这两个表格的例子
public partial class Form1 : Form
{
public Form1(string param1, bool param2)
{
InitializeComponent();
}
//......
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
//......
}
尝试按此方式拨打电话时:
OpenForms<Form1>("a" false); //Error
OpenForms<Form2>();
错误:
必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法'AbrirFormulario(params object [])'
中将其用作参数'T'
答案 0 :(得分:4)
为此,您需要删除new()
约束以允许没有无参数构造函数的表单:
public void OpenForms<T>(params object[] args) where T : Form
现在,为了创建实例,您需要使用Activator.CreateInstance
:
T form = default(T);
if (args == null || args.Length == 0)
form = Activator.CreateInstance<T>();
else
form = (T)Activator.CreateInstance(typeof(T), args);
public void OpenForms<T>(params object[] args) where T : Form
{
Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
if (form !=null)
{
//If the instance is minimized we leave it in its normal state
if (form.WindowState == FormWindowState.Minimized)
{
form.WindowState = FormWindowState.Normal;
}
//If the instance exists, I put it in the foreground
form.BringToFront();
return;
}
if (args == null || args.Length == 0)
form = Activator.CreateInstance<T>();
else
form = (T)Activator.CreateInstance(typeof(T), args);
form.TopLevel = false;
container_panel.Controls.Add(form);
container_panel.Tag = form;
form.Show();
}
答案 1 :(得分:1)
这是一种替代方法,它不需要Form
来实现接口或真正关心它是如何构造的。
假设我们有一个Form
,仅用于测试目的:
public class Form3 : Form
{
public Form3(bool someParameter, string someTitle)
{
}
}
现在有一些关于构造函数的有用的自我记录功能,即参数具有名称。使用这样的东西:
public void OpenForms<T>(params object[] args) where T : Form
{
//...
}
不向调用者提供有关“参数”是什么,它们属于什么顺序或它们的含义的任何信息。所以当你这样称呼它时:
OpenForms<Form3>(true, "Some Value");
Intellisense对你没有帮助,因为它只是表明你需要将一些(或没有)参数传递给方法。相反,更好的方法是使用工厂Func<T>
来构建表单:
public void OpenForms<T>(Func<T> factoryMethod) where T : Form
{
Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
if (form != null)
{
//If the instance is minimized we leave it in its normal state
if (form.WindowState == FormWindowState.Minimized)
{
form.WindowState = FormWindowState.Normal;
}
//If the instance exists, I put it in the foreground
form.BringToFront();
return;
}
form = factoryMethod();
form.TopLevel = false;
container_panel.Controls.Add(form);
container_panel.Tag = form;
form.Show();
}
然后这样调用(请注意你如何也可以省略OpenForms调用的<Form3>
部分,推断它!):
OpenForms(() => new Form3(true, "Title"));
随着所有有用的intellisense伴随着它:
所以现在你有了自我编写代码,无论表单是如何构造的,并且你没有强制一个没有关于哪些参数属于哪里的真实文档(在代码中)的接口。
答案 2 :(得分:0)
另一种解决方案是创建Interface
以创建允许接收参数的方法。
这是一个例子:
public interface IForms
{
void InitializeParameters(params object[] args);
}
这里我们定义一个必须符合实现此接口的表单的方法InitializeParameters
。
稍后,在必须从通用表单调用的表单中,我们在其定义中添加接口,并使用必需的方法:
public partial class Form1 : Form, IForms
{
public Form1()
{
InitializeComponent();
}
public void InitializeParameters(params object[] args)
{
if (args.Length==2)
{
string param1 = args[0].ToString();
int param2 = (int)args[1];
}
else
{
throw new Exception("The number of parameters is incorrect");
}
}
}
现在我们定义通用方法以按以下方式打开表单:
private void OpenForms<T>(params object[] args) where T : Form,IForms, new()
{
Form form;
form= new T();
((IForms)form).InitializeParameters(args);
form.Show();
}
最后,使用它的方法如下:
OpenForms<Form1>("a", 2);
OpenForms<Form2>("a", 2, "b");
OpenForms<Form3>();
必须考虑到,由于已定义了
InitializeParameters
方法,示例2和3 将为不正确数量的参数提供例外。使用此表格,必须控制每个案例。
感谢用户@Pikoh的帮助。