gpt4 book ai didi

c# - 将通用 类传递给表单

转载 作者:可可西里 更新时间:2023-11-01 09:01:47 25 4
gpt4 key购买 nike

我似乎无法通过搜索找到答案,所以这里......

我知道我可以通过使用这种类型的代码将 Class 对象一般地传递​​给其他类:

public class ClsGeneric<TObject> where TObject : class
{
public TObject GenericType { get; set; }
}

然后这样构造:

ClsGeneric<MyType> someName = new ClsGeneric<MyType>()

但是,我有一个应用程序需要我打开一个表单并以某种方式传入通用类型以便在该表单中使用。我正在尝试能够将此表单重新用于许多不同的类类型。

有人知道这是否可行吗?如果可行,怎么做?

我对 Form 构造函数进行了一些试验,但无济于事。

非常感谢,戴夫

更新:澄清我想要达到的结果是什么

enter image description here

更新:8 月 4 日,我已经向前推进了一点,但我为解决方案悬赏。这是我现在拥有的:

interface IFormInterface
{
DialogResult ShowDialog();
}


public class FormInterface<TObject> : SubForm, IFormInterface where TObject : class
{ }

public partial class Form1 : Form
{
private FormController<Parent> _formController;

public Form1()
{
InitializeComponent();
_formController = new FormController<Parent>(this.btnShowSubForm, new DataController<Parent>(new MeContext()));
}
}

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)
{
showSubForm("Something");
}

public void showSubForm(string className)
{
//I'm still stuck here because I have to tell the interface the Name of the Class "Child", I want to pass <TObject> here.
// Want to pass in the true Class name to FormController from the MainForm only, and from then on, it's generic.

IFormInterface f2 = new FormInterface<Child>();
f2.ShowDialog();
}
}

class MeContext : DbContext
{
public MeContext() : base(@"data source=HAZEL-PC\HAZEL_SQL;initial catalog=MCL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework") { }
public DbSet<Parent> Child { get; set; }
}

public class DataController<TObject> where TObject : class
{
protected DbContext _context;

public DataController(DbContext context)
{
_context = context;
}
}

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

结果是:

enter image description here

更进一步,您可以使用 Activator 类从 GenericForm 类中创建类型 TObject 的实例:

GenericType = (TObject)Activator.CreateInstance(typeof(TObject));

在这个例子中,因为我们知道这是一个字符串,我们也知道它应该抛出一个异常,因为字符串没有无参数的构造函数。因此,让我们改用字符数组 (char[]) 构造函数:

GenericType = (TObject)Activator.
CreateInstance(typeof(TObject), new char[] { 'T', 'e', 's', 't' });

MessageBox.Show(GenericType as string);

结果:

enter image description here

那我们做功课吧。以下代码应该可以实现您想要执行的操作。

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

但是,查看您当前的示例,您有两个类,ParentChild。如果我理解正确的话,这些是唯一可能成为 TObject 类型的可能性。

如果是这种情况,那么如果有人将 string 作为类型参数传递(当执行到达 Activator.CreateInstance 时),上面的代码将爆炸 - 带有运行时异常(因为 string 没有无参数构造函数):

enter image description here

为了保护您的代码免受这种情况的影响,我们可以在可能的类中继承一个接口(interface)。这将导致编译时异常,这是更可取的:

enter image description here

代码如下。

// 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;
}
}

这仍然会引发异常,因为您刚刚删除了隐式无参数构造函数。当然,如果您知道自己在做什么,这就很难发生,但是我们可以通过在“where”类型过滤上使用 new() 来禁止这种情况 - 同时也摆脱 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();
}
}

关于c# - 将通用 <TObject> 类传递给表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45462394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com