如何使用此通用方法将参数传递给表单?
How can I pass Parameters to the Form with this Generic Method?
我有这个在面板中打开表单的通用方法,这个方法继承自 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);
Not all forms receive parameters, but in the future, you may need to use 1/2/3 parameters depending on the form.
The parameters can vary in type, either: 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>();
错误:
must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'AbrirFormulario(params object[])'
为此,您需要删除 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();
}
另一种解决方案是创建一个 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>();
It must be taken into account that as the InitializeParameters
method has been defined, examples 2 and 3 will give an exception for an incorrect number of parameters. With this form, each case must be controlled.
感谢用户@Pikoh的帮助。
这是另一种方法,它不需要 Form
来实现接口或真正关心它是如何构建的。
假设我们有一个 Form
,仅用于测试目的:
public class Form3 : Form
{
public Form3(bool someParameter, string someTitle)
{
}
}
现在有一些关于构造函数的有用的自文档特征,即参数有名称。使用这样的东西:
public void OpenForms<T>(params object[] args) where T : Form
{
//...
}
不向调用者提供有关 "arguments" 是什么、它们属于什么顺序或它们的含义的任何信息。所以当你这样称呼它时:
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"));
伴随着所有有用的智能感知:
所以现在您有了自记录代码,表单的构造方式无关紧要,并且您不会强制使用没有关于哪些参数属于何处的真实文档(在代码中)的接口。
我有这个在面板中打开表单的通用方法,这个方法继承自 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);
Not all forms receive parameters, but in the future, you may need to use 1/2/3 parameters depending on the form.
The parameters can vary in type, either:
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>();
错误:
must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'AbrirFormulario(params object[])'
为此,您需要删除 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();
}
另一种解决方案是创建一个 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>();
It must be taken into account that as the
InitializeParameters
method has been defined, examples 2 and 3 will give an exception for an incorrect number of parameters. With this form, each case must be controlled.
感谢用户@Pikoh的帮助。
这是另一种方法,它不需要 Form
来实现接口或真正关心它是如何构建的。
假设我们有一个 Form
,仅用于测试目的:
public class Form3 : Form
{
public Form3(bool someParameter, string someTitle)
{
}
}
现在有一些关于构造函数的有用的自文档特征,即参数有名称。使用这样的东西:
public void OpenForms<T>(params object[] args) where T : Form
{
//...
}
不向调用者提供有关 "arguments" 是什么、它们属于什么顺序或它们的含义的任何信息。所以当你这样称呼它时:
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"));
伴随着所有有用的智能感知:
所以现在您有了自记录代码,表单的构造方式无关紧要,并且您不会强制使用没有关于哪些参数属于何处的真实文档(在代码中)的接口。