也许你已经尝试过了,但你可以创建一个自定义类:
public class GenericForm<TObject> : Form where TObject : class
{
// Here you can do whatever you want,
// exactly like the example code in the
// first lines of your question
public TObject GenericType { get; set; }
public GenericForm()
{
// To show that this actually works,
// I'll handle the Paint event, because
// it is executed AFTER the window is shown.
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
// Let's print the type of TObject to see if it worked:
MessageBox.Show(typeof(TObject).ToString());
}
}
如果您像这样创建它的实例:
var form = new GenericForm<string>();
form.Show();
结果是:
更进一步,您可以使用类TObject
从GenericForm
类中创建类型的实例Activator
:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
在这个例子中,既然我们知道那是一个字符串,我们也知道它应该抛出一个异常,因为字符串没有无参数的构造函数。因此,让我们改用 char 数组 ( char[]
) 构造函数:
GenericType = (TObject)Activator.
CreateInstance(typeof(TObject), new char[] { 'T', 'e', 's', 't' });
MessageBox.Show(GenericType as string);
结果:
那我们来做功课吧。以下代码应该可以实现您想要做的事情。
public class Parent
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child
{
string Name { get; set; }
int Age { get; set; }
}
public class DataController<TObject> where TObject : class
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
但是,查看您当前的示例,您有两个类,Parent
并且Child
. 如果我理解正确,这些是唯一可能成为TObject
.
如果是这种情况,那么如果有人将 astring
作为类型参数传递(当执行到达 时Activator.CreateInstance
),上面的代码将爆炸 - 出现运行时异常(因为string
没有无参数构造函数):
为了保护您的代码免受这种影响,我们可以在可能的类中继承一个接口。这将导致编译时异常,这是更可取的:
代码如下。
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : class, IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : class, IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : class, IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
}
}
更新
正如 RupertMorrish 所说,您仍然可以编译以下代码:
public class MyObj : IAllowedParamType
{
public int Id { get; set; }
public MyObj(int id)
{
Id = id;
}
}
这仍然应该引发异常,因为您刚刚删除了隐式无参数构造函数。当然,如果你知道自己在做什么,这很难发生,但是我们可以通过使用new()
“where”类型过滤来禁止这种情况——同时也可以摆脱这些Activator.CreateInstance
东西。
整个代码:
// Maybe you should give a better name to this...
public interface IAllowedParamType { }
// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
string Name { get; set; }
bool HasChildren { get; set; }
int Age { get; set; }
}
public class Child : IAllowedParamType
{
string Name { get; set; }
int Age { get; set; }
}
// Filter the interface on the 'where'
public class DataController<TObject> where TObject : new(), IAllowedParamType
{
protected DbContext _context;
public DataController(DbContext context)
{
_context = context;
}
}
public class FormController<TObject> where TObject : new(), IAllowedParamType
{
private DataController<TObject> _dataController;
public FormController(Button btn, DataController<TObject> dataController)
{
_dataController = dataController;
btn.Click += new EventHandler(btnClick);
}
private void btnClick(object sender, EventArgs e)
{
GenericForm<TObject> form = new GenericForm<TObject>();
form.ShowDialog();
}
}
public class GenericForm<TObject> : Form where TObject : new(), IAllowedParamType
{
public TObject GenericType { get; set; }
public GenericForm()
{
Paint += GenericForm_Paint;
}
private void GenericForm_Paint(object sender, EventArgs e)
{
MessageBox.Show(typeof(TObject).ToString());
// If you want to instantiate:
GenericType = new TObject();
}
}